MySQL 8.0默认不启用WRITESET并行复制,必须主库配齐binlog_format=ROW、gtid_mode=ON、binlog_transaction_dependency_tracking=WRITESET,从库设slave_parallel_type=LOGICAL_CLOCK且所有表有主键/唯一键,否则即使slave_parallel_workers=16也仅1–2线程工作。

MySQL 8.0 默认不启用 WRITESET 并行复制,即使你设了 slave_parallel_workers=16,从库 SQL 线程大概率仍只用 1–2 个 worker —— 这不是配置没生效,而是 WRITESET 的硬性前提全被跳过了。
主库必须配齐三项才能生成有效 writeset
WRITESET 不是“从库开个开关就能用”的功能,它完全依赖主库在 binlog 中写入正确的依赖信息。漏掉任一条件,从库收到的事务就全是 last_committed=0,直接退化为串行。
-
binlog_format必须为ROW(STATEMENT或MIXED下 WRITESET 彻底失效) -
gtid_mode = ON且enforce_gtid_consistency = ON(GTID 是 WRITESET 定位事务的基础) -
binlog_transaction_dependency_tracking必须设为WRITESET(不是默认的COMMIT_ORDER),同时建议配transaction_write_set_extraction = 'XXHASH64'和binlog_transaction_dependency_history_size = 25000
执行后建议重启 MySQL 或至少确认参数已持久化:SELECT @@binlog_transaction_dependency_tracking; 返回 WRITESET 才算到位。
从库关键参数不能只改 slave_parallel_workers
光调高 slave_parallel_workers 没用,真正决定是否走并行调度路径的是 slave_parallel_type。它的值必须是 LOGICAL_CLOCK,而不是 DATABASE(单库场景下等于没开)或空值。
-
slave_parallel_type = 'LOGICAL_CLOCK'(必须显式设置,不能依赖默认) -
slave_parallel_workers建议设为 CPU 核数的 1.5–2 倍,但别超 16;超过后线程竞争反而拖慢 coordinator -
slave_preserve_commit_order = ON(MySQL 8.0.27+ 默认开启,但若被关过必须手动打开;关掉会导致乱序提交、唯一键冲突等数据错乱) -
log_slave_updates = ON(否则slave_preserve_commit_order失效,WRITESET 调度链断裂)
所有参数需动态生效:STOP SLAVE; SET GLOBAL ...; START SLAVE;,只改变量不启停复制无效。
表结构缺失主键/唯一键会静默退化为串行
WRITESET 的核心是计算每条修改行的唯一键哈希(writeset key)。如果某张表没有 PRIMARY KEY,也没有 NOT NULL UNIQUE 索引,MySQL 就无法提取 key —— 对应事务自动降级为 COMMIT_ORDER 模式,且不报错、不警告。
- 检查方式:
SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema NOT IN ('mysql', 'performance_schema', 'information_schema') AND table_name NOT IN (SELECT table_name FROM information_schema.key_column_usage WHERE constraint_name = 'PRIMARY' OR (constraint_name != 'PRIMARY' AND column_name IS NOT NULL AND nullable = 'NO')); - 典型高危表:日志表、埋点表、历史归档表 —— 它们常被大量并发 INSERT,却无主键,结果所有事务互相阻塞
- 修复不是加索引就行,必须加
PRIMARY KEY或UNIQUE NOT NULL;UNIQUE允许 NULL 的也不行
这类表一旦存在,哪怕其他表都合规,整体并行度也会被严重拖累。
验证是否真生效不能只看 Seconds_Behind_Master
延迟下降可能是偶然抖动,也可能是 IO 提升带来的假象。真实并行状态得查 performance_schema 内部指标:
-
SELECT * FROM performance_schema.replication_applier_status_by_coordinator\G—— 关注WORKERS_PROCESSED是否显著大于WORKERS_WAITING -
SELECT * FROM performance_schema.replication_applier_status_by_worker WHERE WORKER_ID != 0\G—— 看多个 worker 的LAST_SEEN_TRANSACTION是否不同、LAST_APPLIED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP是否有差异 -
SELECT APPLIED_TRANSACTIONS_TOTAL, APPLIED_TRANSACTIONS_IMMEDIATE FROM performance_schema.replication_applier_status_by_coordinator;—— 若APPLIED_TRANSACTIONS_IMMEDIATE / APPLIED_TRANSACTIONS_TOTAL长期低于 0.3,说明 writeset 冲突太多或配置未生效
最直接的证据是 mysqlbinlog --base64-output=decode-rows -v 解析主库 binlog,确认事务 event 中含 write_set 字段 —— 没这个字段,整个 WRITESET 链路就断了。


















