mysql 5.7并行复制需同时设slave_parallel_type='logical_clock'和slave_parallel_workers>0才生效,仅调workers无效;默认database模式下单库事务全归同一worker,无法并行。

因为 MySQL 5.7 默认的 slave_parallel_type=DATABASE 只按库名做哈希分发,多库才能触发多个 worker 线程;单库下所有事务全被塞进同一个 worker,其余线程永远空转。
默认 DATABASE 模式只看库名,不看表或行
MySQL 5.7 的 slave_parallel_type=DATABASE(也是默认值)本质是 coordinator 线程对每个事务的 USE db_name 或语句中显式库前缀(如 app_db.users)做哈希,然后分发到对应 worker。它完全不解析 SQL 内容,也不检查是否改同一张表、同一行。
这意味着:
- 哪怕你有 100 张表都在
app_db下,所有事务都归到同一个 worker,slave_parallel_workers=16也只用 1 个 - 只要主库有
db_a、db_b、db_c三个库在并发写,coordinator 就可能把事务分给 3 个不同 worker 同时执行 - 如果某库写得特别多(比如日志库
log_db占 90% 流量),那对应 worker 会严重过载,其他 worker 大部分时间在Waiting for an event from Coordinator
LOGICAL_CLOCK 不等于自动提速,它依赖主库组提交质量
即使你手动改成 slave_parallel_type=LOGICAL_CLOCK,多库环境也不一定比单库“天然更优”——关键在主库是否真发生了组提交。
主库上事务能否打包进同一 group commit,取决于并发压力和事务提交节奏:
- 低流量场景下,哪怕有多个库,每个事务也可能独占一个 group(
last_committed全不同),从库仍只能串行回放 - 高并发写单库(如秒杀扣库存)反而更容易触发紧凑组提交,只要 binlog_format=ROW + binlog_order_commits=ON,
LOGICAL_CLOCK就能并行 - 多库但各库都是低频定时任务(如每小时跑一次统计),组提交稀疏,
LOGICAL_CLOCK的并行收益也很有限
真正影响并行效果的是事务间依赖,不是库数量
无论是 DATABASE 还是 LOGICAL_CLOCK,底层逻辑都是“无冲突即可并行”。但冲突判断粒度天差地别:
-
DATABASE:粗暴假设“不同库=无依赖”,哪怕db_a.order和db_b.user通过外键或应用逻辑强耦合,也照并行不误——可能出错 -
LOGICAL_CLOCK(未启用 WRITESET):只认组提交批次,同一批次内事务视为可并行,但若两个事务先后更新同一行,靠运气避免冲突 -
LOGICAL_CLOCK+WRITESET(需 MySQL ≥ 5.7.22):才真正分析每条 UPDATE/DELETE 影响的主键/唯一键集合,精确识别行级冲突——这时库数多少已不重要,单库也能高效并行
所以别迷信“多库就快”,先查主库 SHOW GLOBAL STATUS LIKE 'Com_commit' 和 binlog_group_commit_sync_delay,再看从库 SHOW PROCESSLIST 里有多少 worker 处于 Executing event 状态。
容易被忽略的配置陷阱
很多 DBA 改了 slave_parallel_type 就以为万事大吉,但以下三项不配齐,LOGICAL_CLOCK 直接退化成假并行:
- 主库
binlog_format必须为ROW:MIXED在某些函数下切 STATEMENT,STATEMENT根本不记录last_committed - 主库
binlog_order_commits=ON(默认是 ON,但必须SELECT @@binlog_order_commits确认,不能只信文档) - 从库
slave_preserve_commit_order=ON:关掉它,worker 会乱序提交,Seconds_Behind_Master = 0也不代表数据一致
最隐蔽的坑是:这些参数改完要重启复制(STOP SLAVE; START SLAVE;),仅 SET GLOBAL 不生效。











