主從同步中斷是 DBA 最常面對的線上事故之一。本文提供標準化排查流程:看 Master 狀態 → 看 Slave 狀態 → 看錯誤日誌 → 精準修復,涵蓋 IO/SQL 線程異常、同步位點偏移、重複鍵衝突、特殊字元導致的 SQL 報錯等高頻場景。
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 | 98 | | |
+------------------+----------+--------------+------------------+
SHOW PROCESSLIST; 確認有 Binlog Dump 線程,State 為 Has sent all binlog to slave; waiting for binlog to be updated。mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.100
Master_User: repl
Master_Port: 3306
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 98
Relay_Log_File: mysql-relay-bin.000012
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
Slave_IO_Running=Yes、Slave_SQL_Running=Yes、Seconds_Behind_Master=0(或極小)。SHOW PROCESSLIST; 應有兩條 system user 線程:
Waiting for master to send eventHas read all relay log; waiting for the slave I/O thread to update it# 典型路徑
/var/log/mysqld.log
/var/lib/mysql/hostname.err
# 關鍵字搜尋
grep -i "error\|fail\|stop" /var/log/mysqld.log
常見原因:Master binlog 位點變更(如 Master 重啟、binlog 清理、GTID 清除),Slave 仍持有舊位點。
修復步驟:
# 1. 在 Master 獲取最新位點
mysql> SHOW MASTER STATUS;
# 記錄 File、Position,如 mysql-bin.000004, 98
# 2. 在 Slave 重設同步位點
mysql> STOP SLAVE;
mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=98;
mysql> START SLAVE;
# 3. GTID 模式更簡單
mysql> STOP SLAVE;
mysql> CHANGE MASTER TO MASTER_AUTO_POSITION=1;
mysql> START SLAVE;
常見原因:重複鍵衝突、外鍵約束失敗、特殊字元導致 SQL 語法錯誤、DDL 執行失敗。
錯誤日誌典型特徵:
Error "Duplicate entry '1' for key 'PRIMARY'" on query...
修復策略 A:跳過錯誤事務(謹慎使用)
mysql> STOP SLAVE;
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; -- 跳過 1 個事務
mysql> START SLAVE;
適用場景:確認該事務在 Master 已執行、Slave 已有相同資料、跳過不影響一致性(如重複 INSERT IGNORE 類)。
修復策略 B:手動修正資料後繼續
SHOW SLAVE STATUS\G 取得 Last_SQL_Error 具體報錯 SQL。START SLAVE; 繼續同步。修復策略 C:重新同步(資料差異大、無法手動修正)
FLUSH TABLES WITH READ LOCK,記錄位點。mysqldump --master-data=2 --single-transaction 導出。CHANGE MASTER TO 設定位點、START SLAVE。排查:
# 檢查 Slave 處理能力
SHOW PROCESSLIST; -- SQL 線程是否長時間 "Sending data"、"Creating sort index"
# 檢查 Master 壓力
SHOW MASTER STATUS; -- binlog 增長速度
# 檢查網絡
ping/traceroute Master IP
優化:
slave_parallel_workers > 0(5.6+)、slave_parallel_type=LOGICAL_CLOCK 開啟並行複制。binlog_format=ROW、sync_binlog=1、innodb_flush_log_at_trx_commit=1。現象:Last_SQL_Error 顯示 Incorrect string value 或語法錯誤。
根因:Master/Slave 字元集不一致(如 Master utf8mb4、Slave utf8)。
修復:
ALTER DATABASE ... CHARACTER SET utf8mb4、表/欄位同步修改。SET NAMES utf8mb4。| 線程 | 正常 State | 異常 State 範例 |
|---|---|---|
| IO 線程 | Waiting for master to send event | Connecting to master、Reconnecting after a failed binlog dump request |
| SQL 線程 | Has read all relay log; waiting for the slave I/O thread to update it | Executing、Reading event from the relay log、System lock |
Slave_IO_Running!=Yes 或 Slave_SQL_Running!=Yes 或 Seconds_Behind_Master > 300。SHOW SLAVE STATUS\G 記錄 Last_IO_Error、Last_SQL_Error、Master_Log_File、Read_Master_Log_Pos。CHANGE MASTER TO 重設位點 / MASTER_AUTO_POSITION=1。SQL_SLAVE_SKIP_COUNTER=1(確認安全後)。START SLAVE → 連續 3 分鐘 Seconds_Behind_Master=0 → 解除告警。rpl_semi_sync_master=ON,確保至少一份從庫收到 binlog 再回應 Commit,RPO 接近 0。slave_parallel_workers=4(視 CPU 核心數),大幅降低延遲。主從同步穩定性是資料庫高可用的基石。建立「標準化排查、分級修復、預防優於治療」的體系化能力,才能在深夜告警響起時從容應對,守住數據不丟失、服務不中斷的底線。