主从复制难以完全撑住实时写入压力,因从库回放依赖单线程或有限并行线程,高并发下seconds_behind_master易持续上涨;大事务必然导致延迟飙升,单表小事务在并行复制下可基本跟上。

主从复制能撑住实时写入压力吗
MySQL主从复制本身不自动限流,INSERT/UPDATE在主库执行后,从库靠单线程(或并行复制开启后的有限线程)回放binlog。高并发写入下,从库容易延迟——不是复制断了,而是Seconds_Behind_Master持续上涨,有时到几分钟甚至更久。
关键看写入模式:
- 单表高频小事务(如订单状态更新):并行复制(
slave_parallel_type = LOGICAL_CLOCK+slave_parallel_workers > 0)基本能跟上 - 大事务(如
ALTER TABLE、全表UPDATE):必然卡住SQL线程,延迟飙升,且无法拆分
实操建议:
- 迁移前用
pt-table-checksum确认主从数据一致性,别只看Seconds_Behind_Master = 0就以为没问题 - 避免在迁移窗口期执行大事务;若必须,先在从库
STOP SLAVE,等主库跑完再START SLAVE,但会拉长延迟时间 - 监控不能只盯
SHOW SLAVE STATUS,要加performance_schema.replication_applier_status_by_coordinator查实际并行队列堆积
流量切换时怎么避免双写不一致
切流不是改DNS或VIP那么简单。应用层如果还连着旧主库写入,新主库没收到这些变更,立刻就会丢数据。
常见错误现象:
- 切换后部分订单查不到,或状态回滚(旧主库还在收写请求)
- 应用连接池没清空,冷连接复用旧地址
- 中间件(如ShardingSphere、MyCat)配置未同步更新,继续往旧集群转发
实操建议:
- 必须先停写旧主库:用
FLUSH TABLES WITH READ LOCK(注意它会阻塞DML,需快速操作),或更稳妥地用SET GLOBAL read_only = ON+ 检查show global variables like 'read_only'生效 - 切流动作要原子:应用配置更新 + 连接池强制刷新 + 中间件路由规则发布,三者尽量在同一分钟内完成
- 切完立刻验证:在新主库查最新几条写入记录的
gtid_executed,和旧主库对比是否覆盖全部
GTID模式是必须开的吗
不开GTID也能做主从切换,但代价极高:你得手动找binlog filename + position,而高流量下这个位置1秒变好几次,极易配错导致从库跳过或重复执行事件。
GTID让每个事务自带唯一ID(source_id:transaction_id),切换时只要告诉从库“我要追到这个GTID集合”,不用管文件和偏移量。
但要注意兼容性陷阱:
- MySQL 5.6默认关闭GTID,5.7+才支持在线开启,但要求所有节点
enforce_gtid_consistency = ON且无匿名事务(比如老版本mysqldump导出的SQL可能含CREATE TEMPORARY TABLE,触发报错) - 如果旧集群没开GTID,强行升级会失败;此时只能用传统position方式,但务必在低峰期做,且提前演练至少两次定位binlog位置的流程
为什么切完还要跑一次全量校验
复制延迟只是表象,真正危险的是“静默不一致”:比如主库某次INSERT IGNORE因唯一键冲突没插入,但从库因为字符集差异(如utf8mb4_unicode_ci vs utf8mb4_general_ci)判定不冲突,多插了一条;这种差异pt-table-checksum能发现,但普通业务查询根本不会暴露。
所以切流后24小时内必须:
- 对核心表(用户、订单、资金)跑
pt-table-checksum --replicate=test.checksums - 在从库执行
SELECT * FROM test.checksums WHERE master_cnt != this_cnt,逐条修复 - 不要依赖应用层“看起来没报错”——很多不一致是脏读、幻读类问题,日志里根本没错误信息
GTID让切换更稳,但校验不能省;越核心的表,越要当它刚初始化一样重新对一遍。











