首页/数据/数据库速查/大事务对复制的冲击与治理
主从复制与高可用53 条

大事务对复制的冲击与治理

大事务(批量 DELETE/UPDATE、大 LOAD)在从库单线程重放成分钟级延迟,且放大 relay 与锁等待;治理核心是业务侧拆批与限流。

数据库速查数据更新于 2026-10-13

为什么大事务最伤复制

复制重放以事务为单位,单个事务无论多大都只能由一个 worker 执行,并行复制无法把它拆开。所以一次删几百万行、一次大 LOAD,在主库可能几分钟跑完,在从库却要单线程啃到分钟级延迟。表现是延迟阶梯式跳升、relay log 暴涨、从库锁等待升高,治理重心在业务侧拆批与限流。

基本信息

适用MySQL 5.7 / 8.0 主从复制与组复制
机制事务不可分割,并行复制不能拆分单个事务
治理拆成 1000-5000 行一批,控制批量窗口与并发
附带收益缩短备份窗口、降低提交延迟与 undo 增长

现象与判断

现象含义下一步
延迟从秒级跳到分钟级很可能正在重放单个大事务从库看 SQL 线程状态与 innodb_trx 当前事务
relay log 快速增长不回落拉取快于重放,反压严重限制批量窗口,或评估并行复制配置
从库锁等待升高重放的行锁与业务查询冲突错峰执行批量任务,或把批拆得更小
主库提交耗时变长大事务占用 undo 与 redo,刷盘压力集中拆批并控制单事务行数
备份期间写入停滞大事务把备份窗口拉长把批量任务移出备份窗口

批处理拆分示例

批处理拆分示例
-- 反例:一次删 500 万行,从库要单线程啃完
DELETE FROM logs WHERE created_at < '2026-01-01' LIMIT 5000000;
-- 正例:循环小批,每批 2000 行,直到影响行数为 0
DELETE FROM logs WHERE created_at < '2026-01-01' LIMIT 2000;
-- 外壳脚本里循环执行下面这句并判断 affected rows
SELECT COUNT(*) FROM logs WHERE created_at < '2026-01-01';   # 用剩余量判断进度
-- 批量导入同理:LOAD DATA 拆成多个小文件,或分批 COMMIT
-- 监控侧开盘中发现:SHOW REPLICA STATUS\G 观察 Seconds_Behind_Source 是否阶梯跳升

典型使用场景

  • 历史数据归档清理,从单条大 DELETE 改成循环小批
  • 批量导入报表数据,按文件或行数分批提交
  • 从库延迟告警复盘,定位到某个时间点的阶梯式跳升
  • 大表加索引前评估写入影响,避免 DDL 与大事务叠加
  • 组复制环境中控制单事务大小,避免触发大小限制被驱逐
大事务还会拉长主库提交、放大 undo 与 redo 增长,并挤占备份窗口;拆批的收益是全局的,不只是复制延迟。
大事务重放期间 Seconds_Behind_Source 可能长时间不更新,监控看起来没有延迟,实际重放要跑十几分钟,延迟告警要结合 relay log 大小一起判断。

易错点

  • 大事务进行中延迟指标不更新:只信秒级延迟会误判为「复制正常」,需同时看 relay log 与线程状态
  • LIMIT 拆批没有走索引:每一批都全表扫描,拆得越细整体越慢,先确认过滤列有可用索引
  • 在业务高峰执行批量清理:从库锁等待与业务查询互相拖慢,批量任务应放在低谷窗口
  • 只调从库并行参数不拆批:并行复制对小事务有效,单个大事务仍然只能单线程处理

数据来源与参考

  • MySQL 8.0 Reference Manual: Replication and Transactions

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌