发布时间:2026-09-25 04:31 更新时间:2026-09-25 04:31 阅读量:0
MySQL 主从复制跑着跑着突然停了,SHOW SLAVE STATUS 里 Slave_SQL_Running 变成 No,Last_SQL_Error 甩出一行报错——这是很多站长和运维同学都遇到过的场面。真正麻烦的不是报错本身,而是接下来怎么选:直接跳过这条错误让它继续跑,还是把从库重做一遍,又或者干脆重建整条复制链路?选错了,轻则主从数据悄悄不一致,重则几个月后才发现报表数字对不上,回头补数据补到怀疑人生。
本文按「先判断性质、再选手段、最后做校验」的顺序讲一遍,命令以 MySQL 8.0 的常见写法为准,不同小版本或 MariaDB 的细节请以官方文档和实际环境为准。默认你已经能登录主库和从库,并且有 REPLICATION SLAVE、REPLICATION CLIENT 权限。
复制中断的原因大致分两类。一类是数据层面的冲突:比如主库执行了一条 DELETE 或 UPDATE,从库上对应的行不存在,SQL 线程就报 1032(找不到记录)或 1062(主键重复)。另一类是人为或环境层面的问题:有人误在从库上写了数据、从库磁盘写满、表结构在主从两边不一致、大事务把 relay log 撑爆等等。
第一步永远是先看现场,而不是先执行跳过:
SHOW SLAVE STATUS\G
-- 重点看这几行:
-- Slave_IO_Running / Slave_SQL_Running
-- Last_IO_Error / Last_SQL_Error
-- Seconds_Behind_Master
-- Retrieved_Gtid_Set / Executed_Gtid_Set(GTID 模式)如果 Slave_IO_Running 也是 No,说明连主库、拉 binlog 这一步就断了,多半是网络、账号密码或主库 binlog 被清理,先解决 IO 线程,别急着碰 SQL 线程。如果只有 SQL 线程挂掉、IO 线程正常,说明 binlog 已经拉到本地 relay log,只是重放卡住了,这才是本文讨论的重点。
另外还要确认一件事:这条报错的语句在主库上到底改了什么。用报错信息里的 GTID 或位点去主库解析 binlog,看看涉及哪张表、哪几行,心里有数再决定。可以用 mysqlbinlog 按位点或 GTID 范围导出查看,具体参数以官方文档为准。
路线一:跳过当前事务。适合「从库多了一条或少了一条、但业务上可以接受、且能确认这条事务影响面很小」的场景,比如从库被误插入一条测试数据导致主键冲突。操作思路是让 SQL 线程空跑掉这个 GTID 或位点,然后重新启动。GTID 模式下常用 SET GLOBAL sql_slave_skip_counter 在 GTID 开启时是无效的,正确做法是注入一个空事务:
-- 先停掉 SQL 线程
STOP SLAVE SQL_THREAD;
-- 注入空事务,跳过导致报错的那个 GTID(把 xxx 换成实际值)
SET GTID_NEXT='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:1';
BEGIN; COMMIT;
SET GTID_NEXT='AUTOMATIC';
START SLAVE SQL_THREAD;如果是传统位点模式,可以这样跳过一个事件:
STOP SLAVE SQL_THREAD;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE SQL_THREAD;要提醒的是,跳过是把问题藏起来,不是解决掉。每跳一次,主从之间就多一份差异,跳多了后面根本对不上。所以跳过只建议用在「已确认影响极小、且事后会单独补齐数据」的场景,并且一定要做记录。
路线二:重做从库。适合从库数据已经和主库偏差很大、或者从库上被写过脏数据、又或者报错反复跳不完的情况。做法是用主库的备份重建从库数据,再接着复制。常用流程是主库做一次一致性备份(mysqldump 加 --single-transaction --master-data 或 --source-data,MySQL 8.0.26 之后参数名有调整),恢复到从库,然后按备份里记录的 GTID 或位点重新指向主库。备份文件一定要先在测试环境验证能恢复,别等真出事才发现备份是坏的。
路线三:重建复制链路。适合从库还能用、只是想换一台新从库,或者主库做过切换、GTID 集合对不上导致复制无法继续的场景。核心是让新从库拿到一份基线数据,然后 CHANGE REPLICATION SOURCE TO(旧版本是 CHANGE MASTER TO)指向主库。GTID 模式下通常用 SOURCE_AUTO_POSITION=1,让 MySQL 自己算该从哪个事务开始拉:
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='主库IP',
SOURCE_PORT=3306,
SOURCE_USER='repl',
SOURCE_PASSWORD='你的密码',
SOURCE_AUTO_POSITION=1;
START SLAVE;位点模式则要显式写 SOURCE_LOG_FILE 和 SOURCE_LOG_POS,这两个值必须和备份里记录的一致,写错了要么重复重放要么丢事务。
不管走哪条路,恢复完都不能只看 Slave_SQL_Running: Yes 就收工。至少要做三件事:一是确认 Seconds_Behind_Master 归零并稳定一段时间;二是用 pt-table-checksum 这类工具抽查核心表的主从数据差异(工具版本和用法以官方文档为准);三是把这次中断的原因、处理动作、跳过的事务 GTID 记进运维日志,方便以后追查。
平时更值得做的,是给复制加一双「眼睛」:监控 Slave_SQL_Running 和 Seconds_Behind_Master,主库开启 binlog_row_image=FULL 便于定位行级差异,并定期做从库数据校验。复制中断不可怕,可怕的是断了没人知道、或者用跳过的方式让它「看起来正常」。遇到报错,先看性质、再选路线、最后一定校验,这三步走稳,主从才能长期可靠地跑下去。
| 📑 | 📅 |
|---|---|
| 宿主机与容器时间不一致导致接口签名失败排查 | 2026-09-25 |
| Nginx与上游服务时间不同步导致签名校验失败排查 | 2026-09-25 |
| 内核日志里的 OOM 线索:oom_score、cgroup 限制与判断内存不足原因 | 2026-09-25 |
| Linux 服务器 OOM Killer 日志怎么看:dmesg 与 journalctl 定位被杀进程 | 2026-09-25 |
| Nginx 反代后协议错乱:X-Forwarded-Proto 排查与修复 | 2026-09-24 |
| Nginx 上游节点健康检查实战:max_fails、fail_timeout 与 backup 配置 | 2026-09-26 |
| MySQL死锁日志定位实战:读懂SHOW ENGINE INNODB STATUS | 2026-09-26 |
| Linux服务器内存泄漏初判:RSS上涨是缓存还是泄漏 | 2026-09-26 |
| Docker 挂载 NFS 卷卡死排查:stat、df 与 nfsstat 定位失联 | 2026-09-26 |
| PostgreSQL WAL 堆积与复制槽不释放排查实战 | 2026-09-26 |