MySQL主从复制中断后如何安全恢复

    发布时间: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