一、主从复制中断的常见症状

当MySQL主从复制出现问题时,通常会有一些明显的症状。最常见的就是在从库上执行SHOW SLAVE STATUS\G命令时,会发现Slave_IO_RunningSlave_SQL_Running的值变成了"No",或者看到Last_Error字段中出现了具体的错误信息。

有时候错误可能比较隐蔽,比如主从数据已经不一致了,但复制状态仍然显示正常。这种情况下,我们可能需要通过检查表的记录数或者校验数据一致性来发现问题。

# 检查从库复制状态的经典命令
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.100
                  Master_User: repl_user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000123
          Read_Master_Log_Pos: 107
               Relay_Log_File: mysqld-relay-bin.000456
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000123
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1062
                   Last_Error: Error 'Duplicate entry '123' for key 'PRIMARY'' on query. Default database: 'test'. Query: 'INSERT INTO users VALUES (123, '张三')'

二、主键冲突的解决方法

主键冲突是最常见的复制中断原因之一。当从库上已经存在某条记录,而主库又试图插入相同主键的记录时,就会导致复制中断。

解决这类问题通常有几种方法:

  1. 手动删除从库上的冲突记录
  2. 设置sql_slave_skip_counter跳过当前错误
  3. 使用pt-table-checksumpt-table-sync工具修复数据一致性
# 方法1:手动处理冲突记录
mysql> STOP SLAVE;
mysql> DELETE FROM users WHERE id = 123;
mysql> START SLAVE;

# 方法2:跳过当前错误(谨慎使用)
mysql> STOP SLAVE;
mysql> SET GLOBAL sql_slave_skip_counter = 1;
mysql> START SLAVE;

# 方法3:使用Percona工具修复(推荐)
$ pt-table-checksum --replicate=test.checksums h=192.168.1.100,u=root,p=password
$ pt-table-sync --replicate=test.checksums h=192.168.1.100,u=root,p=password --sync-to-master h=192.168.1.101

三、网络中断后的恢复策略

网络问题导致的复制中断通常表现为从库无法连接到主库,或者连接频繁断开。这种情况下,我们需要先解决网络问题,然后再处理复制积压的binlog。

处理步骤通常包括:

  1. 检查网络连接是否恢复
  2. 确认主库的binlog文件是否仍然可用
  3. 重新配置复制起点
# 检查主库当前的binlog状态
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000124 |      107 |              |                  |
+------------------+----------+--------------+------------------+

# 在从库上重新配置复制
mysql> STOP SLAVE;
mysql> CHANGE MASTER TO 
    -> MASTER_LOG_FILE='mysql-bin.000124',
    -> MASTER_LOG_POS=107;
mysql> START SLAVE;

四、大事务导致的复制延迟

当主库执行大事务(比如大批量数据导入或大表结构变更)时,可能会导致从库复制严重延迟甚至中断。这是因为MySQL复制是单线程的,大事务会阻塞后续的所有操作。

解决方案包括:

  1. 将大事务拆分为小事务
  2. 使用基于行的复制格式
  3. 考虑使用多线程复制(MySQL 5.6+)
# 检查当前复制线程状态
mysql> SHOW PROCESSLIST;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time | State                                                  | Info             |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
|  1 | system user |           | NULL | Connect | 1234 | Waiting for master to send event                       | NULL             |
|  2 | system user |           | NULL | Connect | 5678 | Slave has read all relay log; waiting for more updates | NULL             |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+

# 启用多线程复制(MySQL 5.6+)
mysql> STOP SLAVE;
mysql> SET GLOBAL slave_parallel_workers = 4;
mysql> START SLAVE;

五、表结构不一致的处理方法

主从库表结构不一致是另一个常见的复制中断原因。这通常发生在主库执行了DDL变更,但从库因为各种原因没有成功执行。

处理这类问题的步骤:

  1. 确认主从表结构差异
  2. 在从库上手动执行缺失的DDL语句
  3. 重新启动复制
# 检查表结构差异
# 在主库上:
mysql> SHOW CREATE TABLE users\G
# 在从库上:
mysql> SHOW CREATE TABLE users\G

# 手动同步表结构
mysql> STOP SLAVE;
mysql> ALTER TABLE users ADD COLUMN email VARCHAR(100) AFTER name;
mysql> START SLAVE;

六、预防复制中断的最佳实践

与其等到复制中断后再处理,不如提前做好预防措施:

  1. 定期检查复制状态
  2. 设置监控告警
  3. 使用半同步复制提高数据安全性
  4. 定期校验主从数据一致性
# 设置复制监控脚本示例
#!/bin/bash
SLAVE_STATUS=$(mysql -uroot -p -e "SHOW SLAVE STATUS\G" | grep -E "Slave_IO_Running|Slave_SQL_Running" | grep -c "Yes")
if [ "$SLAVE_STATUS" -ne 2 ]; then
    echo "MySQL replication error!" | mail -s "Replication Alert" admin@example.com
fi

# 启用半同步复制
# 在主库上:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;

# 在从库上:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;

七、总结与建议

MySQL主从复制中断是DBA工作中常见的问题,但只要我们掌握了正确的诊断和恢复方法,就能快速解决问题。关键是要理解复制的原理,熟悉常见的错误类型,并建立完善的监控机制。

对于不同的中断原因,我们总结了以下建议:

  1. 主键冲突:优先考虑修复数据一致性,而不是简单跳过错误
  2. 网络问题:确保网络稳定后再处理积压的binlog
  3. 大事务:尽量避免在生产环境执行大事务
  4. 表结构不一致:建立规范的DDL变更流程

记住,预防胜于治疗。建立完善的监控体系,定期检查复制状态和数据一致性,可以大大降低复制中断的风险。