mysql 5.6 mts 并行无效主因是默认 database 模式仅按库分组,单库写入仍串行;需切 logical_clock 模式并调优主从配置。

为什么 slave_parallel_workers 设了却没效果?
MySQL 5.6 的并行复制(MTS)默认只对不同数据库的 DML 并行,如果所有写操作都集中在单个库(比如 db1),哪怕开了 slave_parallel_workers=8,从库仍会串行回放——因为 slave_parallel_type=DATABASE(默认值)只按 USE db_name 或语句中的库名做分组,不识别表级或事务级并发粒度。
实操建议:
- 先确认当前模式:
SELECT @@slave_parallel_type, @@slave_parallel_workers;
- 若业务写入集中于单库,必须切到
LOGICAL_CLOCK模式:SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
- 该模式依赖
binlog_group_commit和last_committed/sequence_number,要求主库开启binlog_order_commits=OFF(否则会人为串行化提交,削弱并行潜力) - 注意:切换后需重启 SQL 线程(
STOP SLAVE SQL_THREAD; START SLAVE SQL_THREAD;),仅改参数不生效
Seconds_Behind_Master 为 0 但延迟真实存在?
这个值只反映 relay log 最后一个事务的提交时间与当前系统时间差,无法体现正在执行的长事务、大事务阻塞后续并行队列,或 IO 线程拉取慢但 SQL 线程空闲的情况。
更准的判断方式:
- 查正在执行的事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), TRX_STARTED)) > 60;
- 看 relay log 进度与 master 的差距:
SHOW SLAVE STATUS\G
对比Relay_Log_File/Relay_Log_Pos和Master_Log_File/Read_Master_Log_Pos - 检查是否卡在某个大事务(如
ALTER TABLE、全表UPDATE)——这类事务即使启用 MTS 也会独占一个 worker,后续事务排队等待
调大 slave_parallel_workers 反而变慢?
不是线程越多越好。worker 数超过物理 CPU 核数(尤其未绑核时),上下文切换开销和锁竞争(如 slave_worker_info 表、relay log 文件读取)会抵消并行收益。
合理设置原则:
- 从
slave_parallel_workers = min(4, CPU核心数 - 1)起步(留至少 1 核给 IO 线程和系统) - 观察
SHOW PROCESSLIST中system user开头的线程数是否稳定达到设定值;若频繁Waiting for an event from Coordinator,说明 coordinator 分发不过来,可能是大事务太多或 relay log 切换太勤 - 避免设成 0 或 1——前者禁用 MTS,后者退化为单线程
- MySQL 8.0.22+ 支持
slave_preserve_commit_order=ON(配合LOGICAL_CLOCK),可防止跨库更新乱序,但会轻微增加 coordinator 压力,非强一致场景可关
主库 binlog 格式和 GTID 对 MTS 的影响
MTS 在 STATEMENT 格式下不可靠:同一语句在主从上可能产生不同结果,且 last_committed 计算基于实际执行顺序,而非解析顺序,容易误判依赖关系。
必须满足:
- 主从均使用
binlog_format=ROW(推荐MIXED不够稳定) - 开启 GTID(
gtid_mode=ON+enforce_gtid_consistency=ON)能提升 MTS 稳定性,因为事务边界更清晰,故障恢复时无需计算 position 偏移 - 但注意:GTID 模式下
sql_slave_skip_counter不可用,跳过错误需用SET GTID_NEXT+ 空事务,操作更谨慎
实际优化中,最常被忽略的是主库 binlog_group_commit 配置和单库写入瓶颈。MTS 不是银弹,它解决的是“可并行事务的调度效率”,而不是“IO 或磁盘慢”“SQL 执行慢”“网络拉取慢”这些底层问题。先确认延迟来源再动参数,否则容易白忙活。











