高并发下binlog卡在writing to binlog是组提交未生效:因binlog_group_commit_sync_delay=0导致无法攒批,虽sync_binlog=1时组提交仍有效,但需真实并发且参数合理配置,否则io放大、锁竞争加剧。

为什么高并发下Binlog写入卡在Writing to binlog
这是典型的组提交未生效表现:show processlist里大量线程停在 Writing to binlog 状态,Performance Schema 中 wait/io/file/sql/binlog 的平均等待时间飙升。根本原因不是磁盘慢,而是 Binlog 写请求没“凑够队”,每个事务都单独走 write + fsync,锁竞争+IO放大。MySQL 5.6+ 默认开启组提交,但默认参数 binlog_group_commit_sync_delay = 0 实际等于关闭攒批逻辑。
sync_binlog=1时group commit还起作用吗
起作用,但必须满足两个前提:一是 sync_binlog = 1(否则组提交的 fsync 合并逻辑被绕过),二是有真实并发写入。单线程压测永远看不到效果——因为没有“follower”可跟。线上业务只要存在多个连接同时 INSERT/UPDATE,组提交就在工作。验证是否生效,别看日志或文档,直接查:SHOW GLOBAL STATUS LIKE 'Binlog_group_commit%',重点关注 Binlog_group_commit_trigger_delay 是否明显上升;如果它长期为 0,说明 delay 没触发,大概率是参数仍为 0 或压测方式不对。
怎么设binlog_group_commit_sync_delay和no_delay_count才不翻车
这两个参数是配合使用的保底机制,不是越大越好:
-
binlog_group_commit_sync_delay单位是微秒,不是毫秒。设 1000(即 1ms)在多数场景已偏高;建议从10~100微秒起步。超过 500 微秒会显著拉高小事务延迟,尤其对金融类短平快操作敏感 -
binlog_group_commit_sync_no_delay_count是“攒够 N 个就发车”的阈值。设太大(如 1000)会导致低流量时事务卡住;设太小(如 2)又容易在高并发下频繁触发,失去合并意义。线上稳妥值是10~50,或干脆保持默认0(完全由 delay 控制) - 必须确保
sync_binlog = 1且innodb_flush_log_at_trx_commit = 1。两者节奏错开(比如后者刷得远快于前者)会导致 Binlog 线程等不到足够事务,“组”自然散掉 - MySQL 5.7.28+ 和 8.0.14+ 才真正支持微秒级 delay;旧版本设非 0 值可能被截断为 0,白配
别碰这些“省事但危险”的替代方案
有人想绕过 Binlog 瓶颈,直接调大 innodb_log_buffer_size 或把 innodb_flush_log_at_trx_commit 改成 2 —— 这两类操作对 Binlog I/O 完全无效:
-
innodb_log_buffer_size只影响 Redo Log 缓冲,和 Binlog 文件写入毫无关系 -
innodb_flush_log_at_trx_commit = 2虽降低 Redo 刷盘开销,但会让 Redo 和 Binlog 提交节奏彻底脱钩,崩溃恢复时极易出现主从数据错位(XID 不匹配) -
sync_binlog = 0或设为很大值(如 1000)看似提升吞吐,实则让 Binlog 组提交逻辑失效,且引入丢日志风险;RDS 环境下还可能引发binlog rotate抖动
真正要盯的,只有三个状态变量:Binlog_group_commit_trigger_delay、Binlog_group_commit_trigger_transaction、Binlog_group_commit_trigger_timeout。前两者明显高于第三个,才说明 delay 和 no_delay_count 配合生效了——其他都是障眼法。











