MySQL主從複製問題總結及排查過程分享

一、概述

mysql主從是常用的高可用架構之一,也是使用最廣泛的的系統架構。在生產環境中mysql主從複製有時會出現複製錯誤問題。

MySQL主從複製中的問題(Coordinator stopped beacause there were errors in the workers......)

二、mysql主從複製原理

mysql主從複製是一個非同步複製過程(總體感覺是實時同步的),mysql主從複製整個過程是由三個執行緒完成。slave端有兩個執行緒(SQL執行緒和IO執行緒),Master端有另一個(IO執行緒)。

MYSQL主從複製過程

在Slave伺服器上執行start slave,開啟主從複製開關。

此時,Slave 伺服器上的 IO 執行緒透過 Master 伺服器上授權複製使用者的請求連線到 Master 伺服器。它還請求從 binlog 日誌檔案的指定位置傳送 binlog 日誌內容。 (配置主從複製任務時執行change master命令時指定日誌檔名和位置)

Master伺服器收到Slave伺服器IO執行緒的請求後,Master伺服器上的IO執行緒是基於Slave的。 伺服器的IO執行緒請求的資訊在指定binlog日誌檔案的指定位置後讀取binlog日誌資訊,然後返回給Slave端IO執行緒。除了binlog日誌內容,在日誌內容返回後Master伺服器端還有一個新的binlog。 binlog 中的檔名和下一個指定的更新位置。

當 Slave 伺服器的 IO 執行緒從 Master 伺服器獲取 IO 執行緒傳送的日誌內容、日誌檔案和位置點時,新增 binlog。日誌內容依次寫入Slave端自身的relay log檔案(mysql-relay-bin。xxxxxx)的末尾。並將新的binlog檔名和位置記錄到master-info檔案中,以便下次讀取Master端新的binlog日誌時,可以告訴Master伺服器從新的binlog日誌中從哪個檔案以及從哪裡開始請求新的binlog日誌內容。

Slave server端的SQL執行緒實時檢測本地relay log中新增的日誌內容,及時relay log。 該檔案的內容被解析成在Master端執行的SQL語句的內容,在Slave伺服器本身按照語句的順序執行SQL的應用。

經過上述過程,可以保證在Master和Slave端執行相同的SQL語句。當複製狀態正常時,Master 端和lave端的資料是完全一致的。

MySQL主從複製問題總結及排查過程分享

三、問題及解決方法

1、show slave status \G 顯示如下報錯資訊:

Coordinator stopped because there were error(s) in the worker(s)。 The most recent failure being: Worker 1 failed executing transaction 。。。

MySQL主從複製問題總結及排查過程分享

2、根據提示資訊定位報錯位置

情況一:"*

*Delete_rows“**

select * from performance_schema。replication_applier_status_by_worker \G

MySQL主從複製問題總結及排查過程分享

原因

:在master上刪除一條記錄,而slave上找不到。

解決方法

: 由於master要刪除一條記錄,而slave上找不到故報錯,這種情況主上都將其刪除了,那麼從機可以直接跳過。

stop slave;set global sql_slave_skip_counter=1;start slave;

如上命令若報錯:ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL。GTID_MODE = ON。 Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction或者可以換用如下命令:

STOP SLAVE;SET @@SESSION。GTID_NEXT= ‘f396f867-d755-11xxx85-005xxxxxb5a:264261655’ ——在session裡設定gtid_next,即跳過這個GTIDBEGIN; COMMIT; ——設定空事物SET SESSION GTID_NEXT = AUTOMATIC; —— 恢復GTIDSTART SLAVE;xxxx

情況二:"Duplicate "

Last_SQL_Error: Could not execute Write_rows event on table xxx;Duplicate entry ‘xxx’ for key ‘PRIMARY’,

原因:在slave已經有該記錄,又在master上插入了同一條記錄

解決方法:在從庫上刪除該記錄,或者跳過該記錄。然後在master上和slave上再分別確認一下。

情況三:"Update_rows" (還未碰到 待驗證)

Last_SQL_Error: Could not execute Update_rows event on table xxx;Can‘t find record in ’xxx‘,

參考原因:在master上更新一條記錄,而slave上找不到,丟失了資料。

參考方法:在master上,用mysqlbinlog 分析下出錯的binlog日誌在幹什麼。

/usr/local/mysql/bin/mysqlbinlog ——no-defaults -v -v ——base64-output=DECODE-ROWS mysql-bin。000010 | grep -A ’10‘ 794 #120302 12:08:36 server id 22 end_log_pos 794 Update_rows: table id 33 flags: STMT_END_F### UPDATE hcy。t1### WHERE### @1=2 /* INT meta=0 nullable=0 is_null=0 */### @2=’bbc‘ /* STRING(4) meta=65028 nullable=1 is_null=0 */### SET### @1=2 /* INT meta=0 nullable=0 is_null=0 */### @2=’BTV‘ /* STRING(4) meta=65028 nullable=1 is_null=0 */# at 794#120302 12:08:36 server id 22 end_log_pos 821 Xid = 60COMMIT/*!*/;DELIMITER ;# End of log fileROLLBACK /* added by mysqlbinlog */;/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;

在slave上,查詢下更新後的那條記錄,應該是不存在的。

mysql> select * from t1 where id=2; Empty set (0。00 sec)

然後再到master檢視

ysql> select * from t1 where id=2;+——+————+| id | name |+——+————+| 2 | BTV |+——+————+1 row in set (0。00 sec)

把丟失的資料在slave上填補,然後跳過報錯即可。

mysql> insert into t1 values (2,’BTV‘);Query OK, 1 row affected (0。00 sec) mysql> select * from t1 where id=2;+——+————+| id | name |+——+————+| 2 | BTV |+——+————+1 row in set (0。00 sec) mysql> stop slave ;set global sql_slave_skip_counter=1;start slave;Query OK, 0 rows affected (0。01 sec)Query OK, 0 rows affected (0。00 sec)Query OK, 0 rows affected (0。00 sec) mysql> show slave status\G;……Slave_IO_Running: YesSlave_SQL_Running: Yes

四、通用解決方法

MySQL主從複製問題總結及排查過程分享

mysql主從複製,經常會遇到錯誤而導致slave端複製中斷,這個時候一般就需要人工干預,跳過錯誤才能繼續 跳過錯誤有兩種方式

4。1 跳過指定數量的事務

mysql>slave stop;mysql>SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1 #跳過一個事務mysql>slave start

4。2 跳所有錯誤或指定型別的錯誤

修改mysql的配置檔案,透過slave_skip_errors引數來跳所有錯誤或指定型別的錯誤

vi /etc/my。cnf[mysqld]#slave-skip-errors=1062,1053,1146 #跳過指定error no型別的錯誤#slave-skip-errors=all #跳過所有錯誤

五、附錄

本文在我的博文上首次發表https://www。cnblogs。com/lkj371/p/15853946。html,喜歡的朋友歡迎點贊關注和轉發!