mysql 5.7+ 并行复制默认仅跨库生效,同库写入仍单线程回放;需设 binlog_format=row、slave_parallel_type=logical_clock、write-set 相关参数,并排查io、sql性能等隐性瓶颈。

为什么 slave_parallel_workers 设了还是不并行?
MySQL 5.7+ 的并行复制默认只对不同数据库(schema)生效,如果所有写操作都在同一个库,哪怕开了 slave_parallel_workers=8,从库也只会用一个线程回放——这是最常被忽略的前提。
- 确认是否满足并行条件:
SHOW SLAVE STATUS\G中看Slave_SQL_Running_State是否长期卡在Reading event from the relay log或Executing event,同时Seconds_Behind_Master持续上涨 - 必须设置
binlog_format = ROW,MIXED或STATEMENT下并行复制基本无效 - 主库需开启
binlog_transaction_dependency_tracking = WRITESET(MySQL 8.0.19+),并配transaction_write_set_extraction = XXHASH64,否则从库无法识别事务间无依赖关系 - 从库设
slave_parallel_type = LOGICAL_CLOCK(别用DATABASE),再调slave_parallel_workers才真正起作用
Seconds_Behind_Master 为 0 却还在延迟?
这个值只反映 relay log 最后一条事件的时间戳和当前系统时间的差,不等于真实数据一致。比如主库停写、从库还没追完 backlog,它可能显示 0;或者主库大事务提交后,从库还没开始执行该事务,它也可能跳回 0 后突然暴涨。
- 更可靠的判断方式是:在主库执行
SELECT UNIX_TIMESTAMP();,在从库执行SELECT MASTER_POS_WAIT('<code>binlog_file',pos, 0);(用SHOW MASTER STATUS当前位点),返回 0 才代表完全追平 - 监控不能只盯
Seconds_Behind_Master,要加Relay_Log_Space(持续增长说明 IO 线程或网络拖慢)、Exec_Master_Log_Pos和Read_Master_Log_Pos差值(IO 落后) - 如果
Slave_SQL_Running_State长期是Waiting for dependent transaction to commit,说明 write-set 依赖检测在起作用,但上游事务粒度太粗(比如单个事务改几百行),反而限制了并行度
调整 slave_parallel_workers 的实际效果很弱?
并行线程数不是越多越好。超过 CPU 核心数(尤其扣除系统和其他服务占用后)会引发锁争用和上下文切换开销,反而降低吞吐。实测中,4–8 是多数 OLTP 场景的合理区间。
- 先查从库负载:
top -H -p $(pgrep mysqld)看线程 CPU 占用是否均匀,如果只有几个线程跑满、其余闲置,说明瓶颈不在并行度,而在磁盘 I/O 或 SQL 回放本身(比如大UPDATE无索引) - 配合调小
innodb_log_buffer_size(避免大事务刷盘阻塞)和增大innodb_read_io_threads/innodb_write_io_threads(加速 redo/undo 处理) - 注意
slave_preserve_commit_order = ON必须开启,否则并行回放可能破坏事务提交顺序,导致主从不一致(尤其涉及AUTO_INCREMENT或INSERT ... SELECT)
主库写入突增时从库瞬间延迟几十秒?
这往往不是复制机制问题,而是从库硬件或配置没跟上主库节奏。例如主库用 NVMe,从库还是 SATA SSD;或者从库 sync_binlog 和 innodb_flush_log_at_trx_commit 都设为 1,而主库已调松。
- 从库可适当放宽持久化要求:
sync_binlog = 1000、innodb_flush_log_at_trx_commit = 2(前提是能接受极端情况下最多丢失 1 秒事务) - 确保 relay log 存放在独立磁盘(别和
datadir共盘),否则写 relay log 和回放 SQL 会抢 IO - 检查网络:用
mysqladmin ping -h slave_ip -uuser -p --sleep=1 --count=100看平均响应是否稳定,丢包或高延迟会直接拖慢 IO 线程
真正卡住同步的,往往不是参数调得不够多,而是某个环节的隐性瓶颈没暴露出来——比如一个没走索引的 DELETE 在从库跑了 30 秒,整个并行队列都得等它。查 SHOW PROCESSLIST 时重点扫 Updating、Deleting、Sending data 状态的线程,比调 slave_parallel_workers 管用得多。











