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
重做从库。