引言

在生产环境中,MySQL主从架构几乎是标配——主库写、从库读,既能分担读压力,又能作为数据备份。但你是否遇到过这种情况?
业务突然报错“主键重复”,查了半天发现是从库多了条脏数据;
刚在主库更新了用户信息,从库查询还是旧数据,延迟监控显示已经落后5分钟;
甚至因为主从数据不一致,灾备切换时直接导致业务中断……

今天咱们就掏心窝子聊聊:MySQL主从数据不一致的那些事儿,从原因到解决,再到预防,手把手教你搞定!


一、主从不一致?先搞懂“复制链路”怎么跑的!

要解决问题,得先明白主从复制的基本流程。简单来说,主从复制分三步:

  1. 主库写Binlog:主库执行写操作时,会把变更记录到二进制日志(Binlog);
  2. 从库拉Binlog:从库的IO线程连接主库,把Binlog拷贝到本地的中继日志(Relay Log);
  3. 从库回放Relay Log:从库的SQL线程读取中继日志,执行里面的SQL语句,同步主库数据。

任何一步出问题,都可能导致主从数据不一致。比如:

  • IO线程拉Binlog卡住了(网络问题/权限不足);
  • SQL线程执行中继日志时报错(数据冲突/DDL不兼容);
  • 甚至人为直接往从库写数据(手贱!)。

二、主从不一致的“罪魁祸首”有哪些?实战场景帮你避坑!

场景1:复制链路断了——IO/SQL线程罢工

现象:登录从库执行SHOW SLAVE STATUS\G,发现:

Slave_IO_Running: No       # IO线程没在跑
Last_IO_Error: Connect   # 连接主库失败
Slave_SQL_Running: Yes    # SQL线程还在跑,但没数据可回放

可能原因

  • 网络不通:主从库防火墙没开3306端口,或者主库IP写错了;
  • 权限不够:从库的复制账号(比如repl用户)没有REPLICATION SLAVE权限;
  • 主库Binlog被删了:主库误操作RESET MASTER,导致从库拉不到最新的Binlog。

解决

  1. 检查网络:用telnet 主库IP 3306测试连通性,不通的话找运维排查防火墙;
  2. 检查权限:主库执行SHOW GRANTS FOR 'repl'@'从库IP';,确保有REPLICATION SLAVE权限;
  3. 修复Binlog:主库别乱删Binlog!如果真删了,只能重置从库(STOP SLAVE; RESET SLAVE ALL;)后重新指向主库。

场景2:复制延迟——从库“跟不上”主库

现象Seconds_Behind_Master显示1000+(表示从库落后主库1000秒),业务查询从库看到旧数据。
可能原因

  • 主库压力大:主库突然来了10万条批量插入,Binlog狂刷,从库SQL线程处理不过来;
  • 从库配置差:从库是低配机器(比如4核4G),CPU/磁盘IO被其他任务占满;
  • 并行复制没开:MySQL 5.7+支持多线程复制(slave_parallel_workers),但默认可能只开1个线程。

解决

  1. 优化主库:大事务拆小(比如批量插入分10次提交,每次1万条);
  2. 升级从库:给从库加CPU、换SSD,确保资源充足;
  3. 开启并行复制:在从库配置文件(my.cnf)里加:
    slave_parallel_workers=8   # 根据CPU核心数调,比如8核设8个
    slave_preserve_commit_order=1  # 保证事务顺序(避免乱序导致数据错误)
    
    改完后重启MySQL生效。

场景3:SQL线程报错——事务没成功回放

现象SHOW SLAVE STATUS\GLast_SQL_Error有具体错误,比如:

Last_SQL_Error: Error 'Duplicate entry '1001' for key 'PRIMARY'' on query

可能原因

  • 数据冲突:主库插入了一条主键为1001的记录,但从库已经有了(比如之前误操作写过);
  • DDL不兼容:主库升级了MySQL版本(比如从5.7升8.0),执行了从库不支持的DDL(比如CHECK约束);
  • 自增ID冲突:主从库auto_increment_increment(步长)或auto_increment_offset(偏移量)配置不一致。

解决

  • 数据冲突:手动删除从库的重复数据(DELETE FROM 表 WHERE id=1001;),然后START SLAVE;恢复复制;
  • DDL不兼容:如果主库版本高,用pt-online-schema-change工具在主库执行DDL(避免锁表),从库会自动同步;
  • 自增ID冲突:确保主从库auto_increment_increment=1auto_increment_offset=1(默认值,一般不会错)。

场景4:人为手贱——直接往从库写数据

现象:业务突然报错“更新失败”,查日志发现从库的某条记录被修改,导致主从数据冲突。
可能原因:开发/测试同学忘记从库是只读的,直接执行了UPDATE操作。

解决

  1. 从库强制只读:在从库配置文件加read_only=1(MySQL 5.7+默认开启,但超级权限用户不受限);
  2. 误操作修复:如果已经写入,先STOP SLAVE;停止复制,删除误操作的数据,再START SLAVE;同步主库最新数据。

三、如何快速检测主从不一致?3个工具搞定!

工具1:SHOW SLAVE STATUS——看状态

执行SHOW SLAVE STATUS\G,重点关注:

  • Slave_IO_RunningSlave_SQL_Running:必须都是Yes
  • Seconds_Behind_Master:理想是0,超过30秒就要警惕;
  • Last_IO_ErrorLast_SQL_Error:有具体错误信息,直接定位问题。

工具2:pt-table-checksum——查数据差异(Percona Toolkit)

这是Percona出的神器,能对比主从表的行哈希值,快速定位不一致的表和行。

安装(Linux):

wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
apt-get update && apt-get install percona-toolkit

使用

pt-table-checksum --databases=your_db --tables=your_table h=主库IP,u=root,p=密码,P=3306

输出示例:

Database: your_db
Table: your_table
Checksum: 1234567890 (主库)
Checksum: abcdef1234 (从库)  # 不一致!

工具3:pt-table-sync——自动修复差异

如果pt-table-checksum发现有差异,用pt-table-sync可以直接同步主库数据到从库(谨慎操作!先备份)。

命令

pt-table-sync --databases=your_db --tables=your_table h=主库IP,u=root,p=密码,P=3306 h=从库IP,u=root,p=密码,P=3306

四、预防主从不一致?这5招必须记牢!

1. 启用半同步复制——主库不“丢”事务

主库提交事务前,必须等从库确认收到Binlog(rpl_semi_sync_master_enabled=1)。这样即使主库崩溃,从库也至少有未提交的事务,避免数据丢失。

配置(主从库都要改my.cnf):

plugin_load=rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_master_enabled=1
rpl_semi_sync_slave_enabled=1

重启MySQL生效。

2. 定期监控——用Prometheus+Grafana盯状态

Prometheus采集MySQL指标(比如Slave_IO_RunningSeconds_Behind_Master),再用Grafana做可视化图表,设置告警(比如延迟>30秒发邮件)。

3. 自动化校验——每天凌晨扫一遍数据

pt-table-checksum写个脚本,每天凌晨业务低峰期执行,自动检测主从差异。如果有问题,触发告警并自动修复(需谨慎)。

4. 禁止直接操作从库——谁写谁背锅!

从库只用于读,所有写操作必须走主库。如果需要从库临时写(比如灾备演练),先停复制、同步数据,操作完再恢复。

5. 主从配置保持一致——版本、参数、字符集全对齐

主从库MySQL版本尽量一致(至少大版本相同);字符集(character_set_server=utf8mb4)、排序规则(collation_server=utf8mb4_unicode_ci)、存储引擎(默认InnoDB)也要一样。


总结:主从一致,运维的“基本功”!

主从数据不一致不可怕,可怕的是不知道怎么排查和解决。记住:

  • 复制状态看SHOW SLAVE STATUS,延迟大了优化主库或从库;
  • 数据冲突用pt-table-checksum查,修复用pt-table-sync
  • 预防比解决更重要:半同步复制、自动化监控、禁止手贱写从库!

下次再遇到主从不一致,你绝对能从容应对~

有其他问题,欢迎在评论区留言!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐