【MySQL】5.6/5.7並行複製bug導致的故障 ERROR 1755/1756

神諭丶發表於2017-07-13
最近做了很多組基於並行複製(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,可以參考:





〇 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錯誤發生不止這一種原因。
 
更多可以參考:


………………
 
其中一個比較有趣的是,MHA作者Yoshinori Matsunobu也遇到了ERROR 1756:

其原因是並行複製並不支援“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 佚名



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29773961/viewspace-2142050/,如需轉載,請註明出處,否則將追究法律責任。

相關文章