转载

【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会有不同)
  1.             ……
  2.                Slave_IO_Running: Yes
  3.             Slave_SQL_Running: No
  4.             ……
  5.             Last_Errno: 1755
  6.             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..
  7.             ……
  8.             Last_IO_Errno: 0
  9.             Last_IO_Error:
  10.             Last_SQL_Errno: 1755
  11.             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..
  12.   Replicate_Ignore_Server_Ids:
  13.             ……

错误提示很明显:
Cannot execute the current event group in the parallel mode
不能在parallel模式下执行目前的这个event组

在5.6作为slave也有可能遇到这个问题。


错误提示和原因显示很明白,关掉并行复制就可以了:
  1. STOP SLAVE;
  2. SET GLOBAL slave_parallel_workers=0;
  3. START SLAVE;

同样是1755报错,目前收集到日志中可能给出的reason有下面三个:
  1. ① Reason:The master event is logically timestamped incorrectly(这个可能也和在5.7上设置slave_parallel_type="LOGICAL_CLOCK"有关)
  2. ② Reason: possible malformed group of events from an old master
  3. 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报错信息:
  1.                 ……
  2.              Slave_IO_Running: Yes
  3.              Slave_SQL_Running: No
  4.                 ……
  5.             Last_Errno: 1756
  6.             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).
  7.                 ……
  8.             Last_SQL_Errno: 1756
  9.             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).
  10.                 ……
此处报错原因:
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的变量:
  1. class MYSQL_BIN_LOG: public TC_LOG
  2. {
  3.   ...
  4.   public:
  5.   /* Committed transactions timestamp */
  6.   Logical_clock max_committed_transaction;
  7.   /* "Prepared" transactions timestamp */
  8.   Logical_clock transaction_counter;
  9.   ...
max_committed_transaction:记录上次提交事务的logical_clock,即last_committed。
transaction_counter:记录当前组提交中各事务的logical_clock,即sequence_number。

而5.6所产生的binlog是没有这些记录的,作为slave的5.7自然无法基于logical_clock进行并行复制。

这种情况下,修正该问题就好说了:
  1. STOP SLAVE;
  2. SET GLOBAL slave_parallel_type="DATABASE";
  3. 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/


正文到此结束
Loading...