MySQL「主從不一致」最常見的成因、快速定位思路以及可落地的修復手段
一、為什么會不一致?14 類高頻場景
類別 | 典型表現/觸發條件 | 快速自檢命令/日志 |
---|---|---|
1. 從庫被寫入 | 業務或 DBA 直連從庫 UPDATE/INSERT | SHOW VARIABLES LIKE 'read_only' 應為 ON |
2. 復制過濾規則 | 主從 binlog-ignore-db / replicate-do-table 不一致 | 比對 my.cnf 過濾規則 |
3. 非 ROW 格式 | STATEMENT 下 UUID() 、NOW() 等不確定函數 | SHOW VARIABLES LIKE 'binlog_format' |
4. 異常宕機 | 主庫 crash 瞬間事務未落盤;從庫 relay-log 損壞 | 錯誤日志出現 Relay log read failure |
5. 從庫斷電 | relay log 截斷 → SQL 線程報錯 1594 | SHOW SLAVE STATUSLast_Errno=1594 |
6. 網絡丟包 | I/O 線程反復重連,少拉日志 | Slave_IO_Running=No 且 Last_IO_Error 提示網絡 |
7. 主從版本差異 | 高版本主庫語法在低版本從庫不支持 | 比對 SELECT VERSION() |
8. sql_mode 不一致 | 嚴格模式主庫插入成功,從庫失敗 | SHOW VARIABLES LIKE 'sql_mode' |
9. server-id 沖突 | 環形/鏈式復制時事件被循環過濾 | SHOW VARIABLES LIKE 'server_id' |
10. 自增步長問題 | 雙主/多主寫入產生重復 PK | auto_increment_increment ≠1 |
11. 大事務+延遲 | 從庫落后幾小時,業務已刪除主庫數據 | Seconds_Behind_Master 持續增大 |
12. 備份恢復方式錯誤 | mysqldump 未加 --single-transaction --master-data=2 | 檢查備份腳本 |
13. 存儲過程/觸發器 | 從庫缺少對應 routine 或觸發器行為不同 | SHOW PROCEDURE STATUS |
14. MySQL Bug | 8.0.27 之前函數索引、JSON 查詢觸發 assert | 搜 bugs.mysql.com + assert 文件名 |
二、快速定位三步走(5 分鐘)
2.1. 看狀態
SHOW SLAVE STATUS\G
關注 4 個核心字段:
Slave_IO_Running
| Slave_SQL_Running
| Last_Error
| Seconds_Behind_Master
2.2. 看日志
tail -n 200 /var/log/mysqld.log | grep -E "Error|Assert|1032|1062|1594"
1032=記錄不存在,1062=主鍵沖突,1594=relay-log 損壞
2.3. pt-table-checksum(可選)
不會可以這個工具評論區告訴我
pt-table-checksum \
--no-check-binlog-format \
--nocheck-replication-filters \
--replicate=ptdb.checksums \
--databases=wewindb \
--tables=test1 \
--recursion-method=dsn=D=ptdb,t=dsns \
h=10.20.17.101,u=root,p=root,P=3306
不一致的表會在 percona.checksums
中生成 diff 記錄。
三、修復方案選擇矩陣
場景 | 推薦方案 | 停機需求 | 速度 | 備注 |
---|---|---|---|---|
僅個別表/少量行 | pt-table-sync | 0 | 分鐘級 | 先 checksum 再 sync |
單表大量不一致 | 重建該表 | 低(可在線導出) | 10~30 min | mysqldump --single-transaction + source |
多表/整庫錯亂 | 重做從庫 | 高 | 慢 | xtrabackup 流式重建最穩 |
relay-log 損壞 | 自動恢復 | 0 | 秒級 | STOP SLAVE; SET GLOBAL relay_log_recovery=1; START SLAVE; |
1032/1062 報錯 | 跳過或補數據 | 0 | 秒級 | SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; 僅應急 |
說明:
從 MySQL 8.0.22 開始,使用 STOP REPLICA 來代替 STOP SLAVE,后者現在已被棄用。 在 MySQL 8.0.22 之前的版本中,請使用 STOP SLAVE。
四、預防措施(生產必做)
4.1. 從庫只讀
read_only=1
super_read_only=1 # 8.0+
4.2. 復制信息落表
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=1
4.3. 格式與一致性
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
4.4. 定期校驗
每月低峰期跑 pt-table-checksum
,差異寫入報警。
4.5. 版本策略
主從同版本 ≥ 8.0.35,避免 8.0.27 之前已知 assert 觸發場景(函數索引、JSON MEMBER OF)。
五、結論
出現主從不一致,先讀 SHOW SLAVE STATUS
和錯誤日志 → 用 pt-table-checksum
檢查 → 能用 pt-table-sync
就不同步整庫;如果修復不了主從不一致,那重做吧, xtrabackup
或者mysqldump
重做從庫。