【MySQL】5.6/5.7并行复制bug导致的故障 ERROR 1755/1756
最近做了很多组基于并行复制(MTS)的主从,其中大多数为5.6->5.7的结构,少部分5.6->5.6的并行复制。
每组m-s结构配置相近,有一定几率出现如下错误,但不是全部出现:
〇 ERROR 1755:
错误场景:
Master(5.6) -> Slave(5.6/5.7)
相关配置:
Slave开启并行复制:
slave_parallel_workers>=1。
Slave报错信息:(此处是5.7的Slave,5.6也类似,但reason会有不同)
-
……
-
Slave_IO_Running: Yes
-
Slave_SQL_Running: No
-
……
-
Last_Errno: 1755
-
Last_Error: Cannot execute the current event group in the parallel mode. Encountered event Gtid, relay-log name {目录}/relaylog/mysql-relay.000002, position 280408 which prevents execution of this event group in parallel mode. Reason: The master event is logically timestamped incorrectly..
-
……
-
Last_IO_Errno: 0
-
Last_IO_Error:
-
Last_SQL_Errno: 1755
-
Last_SQL_Error: Cannot execute the current event group in the parallel mode. Encountered event Gtid, relay-log name {目录}/relaylog/mysql-relay.000002, position 280408 which prevents execution of this event group in parallel mode. Reason: The master event is logically timestamped incorrectly..
-
Replicate_Ignore_Server_Ids:
-
……
错误提示很明显:
Cannot execute the current event group in the parallel mode
不能在parallel模式下执行目前的这个event组
在5.6作为slave也有可能遇到这个问题。
错误提示和原因显示很明白,关掉并行复制就可以了:
-
STOP SLAVE;
-
SET GLOBAL slave_parallel_workers=0;
-
START SLAVE;
同样是1755报错,目前收集到日志中可能给出的reason有下面三个:
-
① Reason:The master event is logically timestamped incorrectly(这个可能也和在5.7上设置slave_parallel_type="LOGICAL_CLOCK"有关)
-
② Reason: possible malformed group of events from an old master
-
③ Reason:the events is a part of a group that is unsupported in the parallel execution mode.
总结一下原因可以是:
在5.6老版本->5.6新版本/5.7的复制结构下,master的event没有记录并行复制的相关信息。
在Slave为5.6和5.7下均有出现的可能,已经被认作是个BUG,可以参考:
https://bugs.mysql.com/bug.php?id=71495
https://bugs.mysql.com/bug.php?id=72537
〇 ERROR 1756
错误场景:
Master(5.6) -> Slave(5.7)
相关配置:
Slave开启并行复制:
slave_parallel_workers>=1。
slave_parallel_type='LOGICAL_CLOCK'。
与1755不同的是,出现1756错误的可能性似乎更多。
Slave报错信息:
-
……
-
Slave_IO_Running: Yes
-
Slave_SQL_Running: No
-
……
-
Last_Errno: 1756
-
Last_Error: … The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state. A restart should restore consistency automatically, although using non-transactional storage for data or info tables or DDL queries could lead to problems. In such cases you have to examine your data (see documentation for details).
-
……
-
Last_SQL_Errno: 1756
-
Last_SQL_Error: … The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state. A restart should restore consistency automatically, although using non-transactional storage for data or info tables or DDL queries could lead to problems. In such cases you have to examine your data (see documentation for details).
-
……
此处报错原因:
Slave的复制分发对象被为“logical_clock”,但5.6是仅支持“database”粒度的并行复制。
那么为什么5.7使用基于logical_clock的就会出现这个问题呢?
因为在5.7的binlog event中,新增了“last_committed”和“sequence_number”
前者表示事务提交时,上次提交的事务编号,若事务具有相同的last_committed,则表明这些事务在同一个组内,可以并行进行apply
这两个的出现,也是5.7新增基于logical_clock进行并行复制的基础。
无论在开启GTID还是关闭GTID的情况下,都会有对应信息的产生。
在5.7源码中,MYSQL_BIN_LOG定义了两个Logical_clock的变量:
-
class MYSQL_BIN_LOG: public TC_LOG
-
{
-
...
-
public:
-
/* Committed transactions timestamp */
-
Logical_clock max_committed_transaction;
-
/* "Prepared" transactions timestamp */
-
Logical_clock transaction_counter;
-
...
max_committed_transaction:记录上次提交事务的logical_clock,即last_committed。
transaction_counter:记录当前组提交中各事务的logical_clock,即sequence_number。
而5.6所产生的binlog是没有这些记录的,作为slave的5.7自然无法基于logical_clock进行并行复制。
这种情况下,修正该问题就好说了:
-
STOP SLAVE;
-
SET GLOBAL slave_parallel_type="DATABASE";
-
START SLAVE;
或者关闭并行复制也可以,即如1755一样,设置slave_parallel_workers=0;
不幸的是,1756错误发生不止这一种原因。
更多可以参考:
https://bugs.mysql.com/bug.php?id=69369
https://bugs.mysql.com/bug.php?id=77239
………………
其中一个比较有趣的是,MHA作者Yoshinori Matsunobu也遇到了ERROR 1756:
https://bugs.mysql.com/bug.php?id=68465
其原因是并行复制并不支持“slave_transaction_retries”
他在rpl_slave.cc发现了该描述:
----
/* MTS technical limitation no support of trans retry */
if (mi->rli->opt_slave_parallel_workers != 0 && slave_trans_retries != 0
复现操作:
1.将slave_transaction_retries设置为一个较高的值
2.开启并行复制:slave_parallel_workers>=0
3.在slave上,对t1表持有一个较长时间的InnoDB锁,比如BEGIN; UPDATE t1 SET a=100;
4.在master上执行一个冲突的语句并提交传输到slave上,比如UPDATE t1 SET a=100 WHERE id=1;
这个bug所造成的ERROR 1756已经在5.7.5被修复。
关于ERROR 1755/1756总结一下:
避免跨版本的并行复制。
升级到5.6.x的更高版本,避免使用老版本5.6的并行复制。
升级到5.7.x的更高版本,避免使用老版本5.7。
〇 参考文档
MySQL 5.7并行复制实现原理与调优 by 姜承尧
从MySQL 5.6到5.7复制错误解决 by 佚名
https://bugs.mysql.com/
正文到此结束