MySQL threads running control

问题背景

线上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权限用户,不做限制

threads running control效果

1000个并发,threads_running飙到1000

threads_running_ctl_default

1000个并发,设置threads_running_high_watermark=500,threads_running维持在500

threads_running_ctl_500

patch下载

thread_running_ctl.patch

《MySQL threads running control》上有9条评论

  1. 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,顺序反过来岂不是有可能节约一次内存分配?

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注