问题背景
线上MySQL经常遇到threads_running飙高的情况,往往在这种情况下,MySQL server会表现出hang住的假象,其实threads_running是一种结果,表示问题已经发生了,如果此时不找出问题原因采取措施,会影响到线上应用,为此我们开发了MySQL threads running control特性,监测threads_running,当发现其超过一个阈值时,server暂时拒绝服务,避免引起雪崩,待threads_running下降后正常服务。
什么是threads_running
threads_running是MySQL一个重要的实时运行状态参数,通过
SHOW STATUS LIKE ‘threads_running’; |
可以查到,它代表的意义:当前并发执行的statement/command的数目,每个statement/command开始执行之前将其增加1,执行结束后减1,代码中的逻辑:
do_command |-->dispatch_command ... inc_thread_running ... mysql_execute_command or execute_some_command ... dec_thread_running ... |
threads_running飙高表示server目前压力较大,一般是客户端压力突增/IO问题/CPU问题/异常SQL等原因引起,需要定位问题源头并马上解决,否则上层应用受到更大影响,为了避免hang住,这时最好的选择是让server暂时“拒载”
threads running control
我们为此开发了这样一个特性:
1. 设置两个阈值,low_watermark和high_watermark和另外一个threads_running_ctl_mode
2. 我们监测系统threads_running状态,在执行query之前,比较一下当前threads_running是否超过high_watermark阈值,如超过直拒绝执行sql,返回客户端:MySQL Server is too busy,若当前threads_running位于high_watermark和low_watermark之间,sleep一段时间(5ms)后重新进入判断逻辑,若query没有被拒绝执行并且累计sleep达到100ms后,server将接受并执行
3. threads_running_ctl_mode控制收到影响的query类型,有2个取值:SELECTS/ALL,默认为SELECTS,表示只影响SELECT语句
4. 对于已经开启的事务和SUPER权限用户,不做限制
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
+
+ if (thread_running_control(thd, (ulong)tr))
+ {
+ my_error(ER_SERVER_THREAD_RUNNING_TOO_HIGH, MYF(0));
+ break;
+ }
请问为何要先执行alloc_query然后再验证running watermark,顺序反过来岂不是有可能节约一次内存分配?
如果不在验证watermark之前alloc_query的话会有问题,你可以试试
必须首先alloc_query,不然会crash,alloc_query不仅仅是分配内存
你好
麻烦一下,
这个patch和mysql 版本有关吗?
mysql 5.6.35 能不能打
patch是diff文件,都是针对特定版本的,文章主要是交流思路,打到不同版本patch会略有不同
网搜和阿里的RDS参数rds_threads_running_high_watermark 高位限流很像啊。作者阿里了,加Q请教
恩,就是这个,已经port到RDS了
请问这个patch要怎么打上去啊?
要懂MySQL源码才能打,不同版本patch有不同,文章主要是交流思路