作者:高鹏(网名八怪),《深入理解MySQL主从原理32讲》系列的作者。
一、问题来源
这是一位朋友的问题,因为前期朋友设置max_binlog_cache_size为8m,后面在线进行了修改了本参数,但是结果导致整个3节点的MGR集群除了primary节点其他两个second节点均掉线。大概的日志如下:
这也是我以前写过的一个过程。
这部分也是我以前记录过的。
max_binlog_cache_size:修改需要使用set global进行修改,定义了binlog cache临时文件的最大容量。如果某个事务的Event总量大于了(max_binlog_cache_size+binlog_cache_size)的大小那么将会报错,如下:
ERROR 1197 (HY000): Multi-statement transaction required more than
'max_binlog_cache_size' bytes of storage; increase this mysqld variable
and try again
我们在函数_my_b_write可以看到如下代码:
if (pos_in_file+info->buffer_length > info->end_of_file) //判断binlog cache临时文件的位置加上本次需要写盘的数据大于info->end_of_file的大小则抛错
{
errno=EFBIG;
set_my_errno(EFBIG);
return info->error = -1;
}
其中info->end_of_file的大小正是来自于我们的参数max_binlog_cache_size。
从second节点的报错来看,是applier线程应用的事务超过了max_binlog_cache_size设置的大小,但是朋友已经修改了其大小,并且主库并没有报这个错误。 我们知道MGR applier线程从启动MGR的那一刻开始就不会停止,类似的master-slave的sql线程也是一样,我们修改参数是通过set global修改的参数,但是实际上在对于MGR的applier线程并不会生效。 但是对于主库来讲,我们修改参数后只要重启应用重新连接那么参数就生效了,这个时候实际上primary session的max_binlog_cache_size和second applier的max_binlog_cache_size并不一致,一旦有主库做一个稍大的事务,如果这个事务的binlog大于以前设置的值,主库虽然能成功,但是备节点就会由于applier线程的max_binlog_cache_size过小而导致备节点脱离整个集群。 对于这一点我们可以通过debug MySQL的sql线程进行验证。
这里我们使用master-slave来进行验证,我们对sql线程进行debug。如下,
可以看到这个值还是老值。
很明显我们刚才修改的值重启sql线程后才生效。 因此故障原因得到证明。
Enjoy MySQL :)
全文完。