主从复制中断的常见原因与恢复方法

主从复制中断的常见原因与恢复方法

概述

MySQL 主从复制在运维中是极易出问题的组件。网络波动、数据冲突、配置变更等都可能导致复制中断。了解常见的中断原因和恢复步骤,是 DBA 的核心技能。

复制中断的两种类型

I/O 线程中断

I/O 线程负责从主库拉取 Binlog,如果中断,从库不再接收新数据。

SHOW SLAVE STATUS\G
-- Slave_IO_Running: No        ← I/O 线程中断
-- Slave_SQL_Running: Yes      ← SQL 线程正常
-- Last_IO_Error: ...          ← 错误信息

SQL 线程中断

SQL 线程负责回放 Relay Log,如果中断,数据停止同步。

SHOW SLAVE STATUS\G
-- Slave_IO_Running: Yes       ← I/O 线程正常
-- Slave_SQL_Running: No       ← SQL 线程中断
-- Last_SQL_Error: ...         ← 错误信息

常见中断原因及恢复

1. 网络中断

症状

Last_IO_Error: error reconnecting to master 'repl@192.168.1.10:3306' - 
retry-time: 60  retries: 1, message: Can't connect to MySQL server on '192.168.1.10' (110)

原因:主库宕机、网络抖动、防火墙拦截。

恢复

# 1. 检查网络
ping 192.168.1.10
telnet 192.168.1.10 3306

# 2. 确认主库运行正常
mysql -h 192.168.1.10 -u root -p -e "SELECT 1"

# 3. 从库上启动复制
START SLAVE;

预防:部署在同一内网、避免跨机房、配置网络监控。

2. 主键冲突

症状

Last_SQL_Error: Error 'Duplicate entry '100' for key 'PRIMARY'' on query. 
Default database: 'test'. Query: 'INSERT INTO users(id, name) VALUES(100, 'Alice')'

原因:从库上误写了数据,与主库同步过来的数据冲突。

恢复

-- 第一步:查看冲突的具体记录
SELECT * FROM users WHERE id = 100;
-- 确认从库中已存在 id=100 的脏数据

-- 第二步:删除脏数据
DELETE FROM users WHERE id = 100;

-- 第三步:跳过该事务(不推荐永久跳过)
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;

更好的恢复方式(GTID 模式)

-- 跳过指定 GTID 的事务
-- 1. 找到冲突的 GTID
SHOW SLAVE STATUS\G
-- Executed_Gtid_Set 和 Retrieved_Gtid_Set

-- 2. 手动注入该 GTID 作为已执行
SET GTID_NEXT = '3e11fa47-61ca-11e8-9e70-00163e114761:123';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;

预防:从库必须设置 read_only = ON,防止误写。

3. 从库事务比主库大

症状

Last_SQL_Error: Could not execute Write_rows event on table test.orders; 
Duplicate entry '5000' for key 'PRIMARY', Error_code: 1062; 
handler error HA_ERR_KEY_NOT_FOUND; 

原因:从库上执行了大事务的 INSERT…SELECT,或者从库自增值超前。

恢复

-- 方法 1:手动处理冲突后跳过
SET GLOBAL sql_slave_skip_counter = 1;

-- 方法 2:GTID 模式下跳过
SHOW SLAVE STATUS\G
-- 获取 Last_Executed_Transaction
SET GTID_NEXT = '<冲突事务的 GTID>';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;

4. 主库 Binlog 被清理

症状

Last_IO_Error: Got fatal error 1236 from master when reading data 
from binary log: 'The slave is connecting using CHANGE MASTER TO 
MASTER_AUTO_POSITION = 1, but the master has a purged binary log 
containing the GTIDs that the slave requires.'

原因:主库清理了 Binlog,从库需要的 Binlog 已经不存在了。

恢复

-- 方法 1:从最新位置重新同步(会丢失部分数据)
STOP SLAVE;
CHANGE MASTER TO MASTER_AUTO_POSITION = 0,
    MASTER_LOG_FILE = 'mysql-bin.000045',  -- 主库当前最新的 Binlog
    MASTER_LOG_POS = 4;                     -- 从头开始
START SLAVE;

-- 方法 2:重新搭建从库(数据安全)
-- 1. 主库导出数据
-- mysqldump --all-databases --master-data=2 > dump.sql
-- 2. 从库导入
-- mysql < dump.sql
-- 3. 设置新的同步点

预防:设置合理的 Binlog 过期时间,监控从库延迟:

binlog_expire_logs_seconds = 604800  -- 保留 7 天

5. 表结构不一致

症状

Last_SQL_Error: Error 'Unknown column 'email' in 'field list'' on query. 
Query: 'ALTER TABLE users ADD COLUMN email VARCHAR(100)'
-- 或者
Last_SQL_Error: Error 'Can't find file: './test/users' (errno: 2)' 

原因:主库和从库的表结构不同(手动在其中一个改了)。

恢复

-- 1. 比较主从表结构
SHOW CREATE TABLE users;  -- 主库和从库分别查看

-- 2. 在从库上执行 ALTER 使结构一致
ALTER TABLE users ADD COLUMN email VARCHAR(100);  -- 如果从库缺少

-- 3. 启动复制
START SLAVE;

中断恢复流程

发现复制中断(监控告警)
    │
    ├── 查看 SHOW SLAVE STATUS
    │
    ├── Slave_IO_Running: No
    │   ├── 检查网络(ping + telnet)
    │   ├── 检查主库是否运行
    │   ├── 检查 Binlog 是否被清理
    │   └── START SLAVE
    │
    └── Slave_SQL_Running: No
        ├── 查看 Last_SQL_Error
        ├── 检查数据是否冲突
        ├── 处理冲突(删除/更新数据)
        ├── 跳过事务(sql_slave_skip_counter 或 GTID 注入)
        └── START SLAVE

恢复后的验证

-- 1. 检查复制状态
SHOW SLAVE STATUS\G
-- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes

-- 2. 验证延迟在减小
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 减少趋势 ✅

-- 3. 检查数据一致性
-- 对比主从的关键表行数
SELECT COUNT(*) FROM users;  -- 主库和从库分别执行

面试要点

  1. 最常见的中断原因:主键冲突(从库误写)、网络中断、Binlog 被清理
  2. 两类线程中断:I/O 线程(拉取问题)和 SQL 线程(回放问题)
  3. 恢复通用步骤:看错误信息 → 解决根本原因 → START SLAVE
  4. 从库必须设置 read_only=ON,防止误写导致复制中断
  5. GTID 模式恢复更友好:可以通过 GTID 定向跳过特定事务
  6. 预防胜于恢复:合理配置 Binlog 保留、监控延迟、从库只读
© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容