mysql wating for_MySQL:关于Wating for Slave workers to free pending events等待

###一、问题来源

这是一位朋友给我的一个截图,说show slave status一直处于Wating for Slave workers to free pending events状态,这个库是MTS从库,版本为5.7.25

![image.png](https://upload-images.jianshu.io/upload_images/7398834-9041e43c7f636efc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

###二、关于等待

我曾经在我的主从原理系列中(已经成书)解释过大部分协调线程的等待,如下:

- “Waiting for dependent transaction to commit”

由于协调线程判定本事务由于last commit大于current\_lwm因此不能并行回放,协调线程处于等待,大事务会加剧这种情况。

- “Waiting for slave workers to process their queues”

由于没有空闲的工作线程,协调线程会等待。这种情况说明理论上的并行度是理想的,但是可能是参数slave\_parallel\_workers设置不够。当然设置工作线程的个数应该和服务器的配置和负载相结合考虑。

- “Waiting for Slave Worker queue”

由于工作线程的任务队列已满,协调线程会等待。这种情况前面说过是由于一个事务包含了过多的Event并且工作线程应用Event的速度赶不上协调线程分配Event的速度,导致了积压并且超过了16384个Event。

但是对于Wating for Slave workers to free pending events等待,只是简单的提及了可能涉及到big event,这里想说的就是实际上这个等待可能和两方面有关:

1. 如果涉及到big event,那么要求worker线程当前没有积压的event正在执行

2. 如果不是big event,那么需要判断当前worker线程积压的event大小加上本次进入worker线程对列的event大小之和不能超过参数slave_pending_jobs_size_max的大小

什么是big event呢?很简源码判断如下:

```

bool big_event= (ev_size > rli->mts_pending_jobs_size_max);

```

遇到这种问题应该在日志中能够看到

```

2020-10-28T14:07:49.522388+08:00 14 [Note] Multi-threaded slave statistics for channel '': seconds elapsed = 676;.....waited due the total size 的大小不为0。

```

###三、判断的维度

这里我们简单考虑一下判断一下可以进入worker线程队列的维度。首先我们说对于woker线程队列来讲他有一个固定的大小也就是积压不能超过16384个event,这里我们还明白来,这些积压的event还不能太大,如果太大就会出现Wating for Slave workers to free pending events等待,因此总结一下:

- 如果协调线程发现分配的woker线程积压的event个数超过了 16384个event,那么进入Waiting for Slave Worker queue等待

- 如果协调线程发现分配的worker线程积压的event的大小超过了slave_pending_jobs_size_max设置的大小,那么进入Wating for Slave workers to free pending events等待

当然这是从个数和大小两个不同的维度来判断的,如果一个大事务,我们知道这样的事务会形成很多8K左右的event(比如一次delete了1000W的数据),那么如果只用个数来判断那么就是积压的event大小最多达到(8K*16384=128M),实际上我们的参数slave_pending_jobs_size_max 默认为16M,这种情况下可能协调线程会先触发Wating for Slave workers to free pending events等待。

因此不管是触发了Waiting for Slave Worker queue等待还是Wating for Slave workers to free pending events等待,我们都需要检查一下worker线程回放event的效率是不是遇到了问题。

###四、关于源码等待

函数入口append_item_to_jobs

- 关于等待,如下:

```

bool big_event= (ev_size > rli->mts_pending_jobs_size_max);

/*

C waits basing on *data* sizes in the queues.

If it is a big event (event size is greater than

slave_pending_jobs_size_max but less than slave_max_allowed_packet),

it will wait for all the jobs in the workers's queue to be

completed. If it is normal event (event size is less than

slave_pending_jobs_size_max), then it will wait for

enough empty memory to keep the event in one of the workers's

queue.

NOTE: Receiver thread (I/O thread) is taking care of restricting

the event size to slave_max_allowed_packet. If an event from

the master is bigger than this value, IO thread will be stopped

with error ER_NET_PACKET_TOO_LARGE.

*/

while ( (!big_event && new_pend_size > rli->mts_pending_jobs_size_max)//条件1

|| (big_event && rli->mts_pending_jobs_size != 0 ))//条件2

{

rli->mts_wq_oversize= TRUE;

rli->wq_size_waits_cnt++; // 增加由于big event或者积压大小过多导致的等待次数

thd->ENTER_COND(&rli->pending_jobs_cond, &rli->pending_jobs_lock,

&stage_slave_waiting_worker_to_free_events, &old_stage);//进入等待状态

mysql_cond_wait(&rli->pending_jobs_cond, &rli->pending_jobs_lock);//等待条件变量

mysql_mutex_unlock(&rli->pending_jobs_lock);

thd->EXIT_COND(&old_stage);

if (thd->killed)

return true;

if (rli->wq_size_waits_cnt % 10 == 1)

sql_print_information("Multi-threaded slave: Coordinator has waited "

"%lu times hitting slave_pending_jobs_size_max; "

"current event size = %zu.",

rli->wq_size_waits_cnt, ev_size);

mysql_mutex_lock(&rli->pending_jobs_lock);

new_pend_size= rli->mts_pending_jobs_size + ev_size;

}

```

- 关于唤醒,如下:

当woker线程执行完event后,会进行减去执行完event size的操作如下,入口函数remove_item_from_jobs:

```

减去执行完event size

rli->mts_pending_jobs_size-= ev->common_header->data_written;

唤醒

/* coordinator can be waiting */

if (rli->mts_pending_jobs_size < rli->mts_pending_jobs_size_max &&

rli->mts_wq_oversize) // TODO: unit/general test wq_oversize

{

rli->mts_wq_oversize= FALSE;

mysql_cond_signal(&rli->pending_jobs_cond);

}

```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值