实为吾之愚见,望诸君酌之!闻过则喜,与君共勉
第一节 并行复制
Mysql5.6的mts(并行复制)是基于database来分发事务的,coordinator(原来的sql thread)按照slave worker与db的对应关系进行处理来分发事务给相应的slave worker,slave worker代替了sql thread来执行事务中的event。并且mysql默认认为数据是以database来分布的,跨库的事务在slave应用的时候可能就需要等待了。
Waiting for Slave Worker to release partition第一次看到是在开启MTS的mysql5.6主从复制的时候,在Slave_SQL_Running_State:出现Waiting for Slave Worker to release partition,Slave_SQL_Running_State的状态比较多,但是这个状态翻译过来是指“等待slave worker 释放 分区(partitions)”,其中的partitions解释成中文不是很正确,partitions可以理解成”按照slave worker与db的对应关系进行分发事务后的对象”(有更好的解释请留言),它既不是事务也不是event,也不是单纯的对应关系,起码可以确定这种情况并不是异常的情况(大部分时候),slave worker正在应用coordinator分配的内容但是还没结束,coordinator需要等待之前分配的内容应用完成才可以继续分配(coordinator还没有将其放入slave worker的queue),下面尝试测试和复现Waiting for Slave Worker to release partition。
当不开启并行复制时(slave_parallel_workers
为0),show processlist是这样的:
当开启并行复制时(slave_parallel_workers为2),show processlist是这样的:
区别是增加了两个slave worker进程,原来的sql thread变成了 coordinator。
第二节 测试和复现
2.1 创建测试数据
1,创建两个测试的database:slavetest,slavetest1
2,在这两个db中分布创建一张表test,向里面写入200w左右的测试数据
通过测试一些场景,通过其结果来反应一些问题,以下测试多是基于自建mysql进行
2.2 测试1
确认slave worker与db的在串行执行时对应关系,先打开一个session,分别执行
update slavetest.test set trade='slavetest';
update slavetest1.test set trade='slavetest1';
查看slave的slave worker状态,找到slavetest对应的slave worker
通过上面测试slavetest对应的slave worker的进程id为5812476
使用同样的方法,得出如下对应:
slavetest 5812476
slavetest1 5812475
这样单线程执行的时候,两个db在执行update更新时,coordinator都分配给了5812476的slave worker
2.3 测试2
确认slave worker与db的在并行执行时对应关系,同事打开2个session,每个session分别执行更新,中间间隔10s
update slavetest.test set trade='slavetest11';
update slavetest1.test set trade='slavetest22';
查看slave的slave worker状态,找到slavetest对应的slave worker(可以写一个脚本来循环执行show processlist监控)
通过执行信息看,slavetest1的事务先完成,slavetest2的事务后完成,看下slave的进程信息:
过滤后如下:
通过上面测试并不能在slave上执行完这两个事务的时候,保证一个slave worker完全对应其中的一个dbname(个人以为上一个事务里面,slave worker与db的对应是不会变的),暂且得出的结论是当并行执行两个db的事务的时候,其中的两个slave worker都产生了影响。
这样多线程执行的时候,两个db在执行update更新时,coordinator会把事务分配给两个slave worker同时并行执行,并且也出现了Waiting for Slave Worker to release partition,并且还出现了Waiting for Slave Worker queue,按照之前的描述,mysql假设数据是按照database来分布的,所以不会存在跨库的情况,下面进行事务跨库的测试
2.4 测试3
确认slave worker与db的在一个事务里跨库执行时对应关系,只打开1个session,执行:
begin;
update slavetest.test set trade='slavetest1';
update slavetest1.test set trade='slavetest2';
commit;
查看slave的slave worker状态,找到slavetest对应的slave worker(可以写一个脚本来循环执行show processlist监控)
模拟一个事务内跨库执行更新,查看slave的进程信息:
通过过滤的结果看,执行event的进程只有一个5812476,coordinator并没有分配给5812475的slave worker来执行,且也出现了Waiting for Slave Worker to release partition
通过测试和复现问题,Waiting for Slave Worker to release partition一般来说是一个正常的中间状态,但是也有可能出现问题,有一些特殊情况可以参考:
https://bugs.mysql.com/bug.php?id=73066
https://bugs.mysql.com/bug.php?id=72794
另外包括Waiting for Slave Worker queue,System lock等状态大部分也是正常的中间状态