Seconds_Behind_Master不可信,真实延迟需用pt-heartbeat监控;write_set并行复制需满足无跨表更新等条件;从库DDL会卡住复制,应避免手动执行;读写分离不保证强一致,关键路径须直连主库或等待GTID追平。

Seconds_Behind_Master 显示为 0,但实际数据已延迟
这个值不可信。它只在 SQL 线程正常运行、且主从系统时间一致时才接近真实延迟;遇到大事务(比如 DELETE FROM huge_table WHERE ...)、并行复制开启、或主从服务器时钟偏差 >1s 时,Seconds_Behind_Master 会突然跳变或长期卡在 0。线上必须弃用它做核心告警依据。
真正可靠的方案是部署 pt-heartbeat:在主库每秒更新一张心跳表 heartbeat.heartbeat,从库读取该表时间戳与本地时间差作为真实延迟。注意:pt-heartbeat 必须用同一数据库用户、走相同网络链路,否则测出来的是网络抖动而非复制延迟。
- 避免把心跳表建在
information_schema或临时库中——这些库不参与复制 - 心跳表必须带主键且无大字段,否则自身写入也会被慢日志捕获、干扰判断
- 监控阈值建议设为 500ms 而非 1s:短延迟累积快,等 1s 才告警往往已错过黄金处理窗口
MySQL 8.0 开启 write_set 并行复制后仍延迟高
启用 slave_parallel_type = LOGICAL_CLOCK 和 slave_parallel_workers = 8 是基础,但 write_set 并行真正生效的前提是:主库必须开启 binlog_transaction_dependency_tracking = WRITESET(默认值),且事务之间无跨表更新、无函数依赖(如 NOW()、UUID())、无 DDL 混合写入。否则从库会退化为单线程回放。
验证是否生效:查从库 SHOW PROCESSLIST,看到多个 Worker thread 处于 Executing 状态才算真并行;若只有 1 个线程活跃,说明事务间存在隐式依赖,write_set 失效。
- 禁止在事务中调用
SELECT ... FOR UPDATE后再更新另一张表——这会污染 write_set 哈希值 - 批量 INSERT 优先用
INSERT ... VALUES (...), (...), (...)单语句,而非多条独立 INSERT——后者每个语句生成独立 write_set,无法合并调度 - 升级到 MySQL 8.0.23+,修复了早期版本中分区表 write_set 计算错误导致的串行回放 bug
从库执行 ALTER TABLE 导致复制卡死
DDL 在从库不是“原样执行”,而是先加 MDL 锁、再等待所有活跃查询释放锁,最后才开始变更。如果从库正跑着报表查询(SELECT COUNT(*) FROM orders GROUP BY created_date),SQL 线程就会无限期阻塞,Seconds_Behind_Master 看似不动,实际 relay log 已堆积数 GB。
解决思路不是“加速 DDL”,而是让 DDL 不卡住复制流:主库执行 DDL 前,先用 pt-online-schema-change 改表;或者在从库上设置 slave_ddl_exec_mode = IDEMPOTENT(MySQL 8.0.26+),允许跳过已存在的列变更。
- 禁止在从库手动执行任何 DDL——包括
CREATE INDEX,哪怕只是为慢查询加索引 - 检查
SHOW PROCESSLIST中是否有状态为Waiting for table metadata lock的线程,这是最直接的卡顿证据 - 若已卡住,不要 kill SQL 线程,应先
KILL阻塞它的 SELECT 进程,再等 SQL 线程自动恢复
业务刚写完就查从库,结果查不到最新数据
这不是复制问题,是架构误用。读写分离中间件(如 ShardingSphere、ProxySQL)无法保证“写后即读”,除非你显式指定 /*+ FORCE_MASTER */ 注释或开启强一致性路由。普通读请求发给从库,就是接受一定延迟的妥协。
真正要解决的是“关键路径强一致”:用户注册后查个人资料、支付成功后查订单状态、库存扣减后查剩余量——这些场景必须直连主库,或使用 GTID + WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS 等待从库追平。
- 不要依赖
SELECT ... FOR UPDATE在从库加锁来规避延迟——从库的锁不阻塞主库写入,毫无意义 - 应用层缓存(Redis)里存的“最新状态”必须和主库写操作在同一事务提交后更新,否则缓存和数据库永远不同步
- 如果必须读从库,至少加
SLEEP(100)(毫秒级)再查——对用户体验影响远小于数据错乱
slave_parallel_workers,而是每天看一眼 pt-heartbeat 的 P99 延迟曲线,再顺手 SHOW PROCESSLIST 扫一遍从库有没有 Waiting for table metadata lock。


















