<b>現象描述</b>
在5.6主備環境下,主備都開啟gtid-mode,備庫開啟crc校驗,主庫不開。重新開機備庫sql線程後,備庫sql線程停止last_error顯示:relay log read failure: could not parse relay log event entry. <b>the possible reasons are: the master's binary log is corrupted</b>(you can check this by running 'mysqlbinlog' on the binary log), <b>the slave's relay log is corrupted</b> (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's mysql code. if you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'show slave status' on this slave.
從錯誤資訊可以看出,可能是主庫的binlog或備庫的relaylog出錯。
<b>關于gtids</b>
詳見上一章節:mysql· 限制改進·gtid和更新
<b>binlog頭部資訊</b>
format_description:binlog格式資訊,備庫解析binlog的标準。
previous_gtids_log:已産生的gtid集合,防止重複記錄binlog。
rotate:備庫binlog切換到主庫binlog的轉換标志。
<b>previous_gtids_log</b>
開啟gtid_mode時,每個binlog檔案的頭部會有一個previous_gtids_log,用于儲存已産生的gtid。mysql源碼中的gtid_set類用于實作這個功能,内部由連結清單實作,連結清單的每個節點儲存了一個區間,用于指代一段連續的gno。
<b>分析和修複</b>
在上述環境下,備庫relay log的前幾條應該是:
之前備庫選取format 的政策是:先根據檔案頭備庫的format_description_event确定format,然後繼續向下讀;
如果讀到format_description_event,則更新format;如果讀到rotate_event,則繼續向下讀;
如果讀到一條非format_description_event或rotate_event的log,則停止更新format,選取目前format解析後面的log。
由備庫前幾條relay log可知,讀到第二條previous_gtids_log_event時,已由備庫的format_description_event确定format(binlog_checksum=on),而略過主庫的format_description_event。
到下面解析log時,會認為每條log尾部有crc校驗資訊。但校驗資訊實際是不存在的,是以會報crc校驗的錯誤。
當讀到previous_gtids_log_event時繼續向下讀,即可讀到主庫的format_description_event,解決這個bug。
<b>其他複現場景</b>
5.5/5.1會作為5.6的主庫,此時備庫開啟gtid-mode和crc校驗。若中間出現主鍵沖突等錯誤,sql thread暫停後, 執行start slave,會報錯 "event crc check failed"。原因是5.5/5.1不支援crc校驗,和5.6不開啟crc校驗相似。