mysql 5.7高并发写入卡在log_sys->mutex全局锁上,该锁保护redo log buffer的分配、拷贝、lsn更新与刷盘协调,所有事务(哪怕只改一行)都必须串行争抢;调大innodb_log_file_size无效,应增大innodb_log_buffer_size并设innodb_flush_log_at_trx_commit=2缓解争用。

MySQL 5.7 高并发写入卡在事务日志上,根本原因不是磁盘慢或配置没调够,而是 log_sys->mutex 这把全局锁成了串行瓶颈——所有事务提交都得排队抢它,QPS 一过 2000 就明显掉吞吐。
log_sys->mutex 是什么,为什么它会卡住所有写入?
这把锁保护的是整个 redo log buffer 的分配、拷贝、LSN 更新和刷盘协调逻辑。它不按事务拆分,也不按页隔离,只要涉及写日志(哪怕只改一行),就必须先拿到这把锁。
- INSERT/UPDATE/DELETE 修改数据 → 必须记 redo → 必须进
log_sys->mutex临界区 - 即使事务很小,也要走完整路径:分配 buffer 空间 → 拷贝日志内容 → 更新内存 LSN → 判断是否触发刷盘
- 当
innodb_flush_log_at_trx_commit = 1(默认)时,每次 COMMIT 都强制 fsync,锁持有时间被 I/O 延迟拉长,排队更严重 - 在
SHOW ENGINE INNODB STATUS中常看到大量线程挂起在log_write_up_to或log_flush_up_to,OS WAIT ARRAY 显示它们正在自旋等待log_sys->mutex
调大 innodb_log_file_size 能缓解吗?
不能。这个参数控制的是磁盘上 redo log 文件大小,影响 checkpoint 频率和 crash recovery 时间,但完全不参与 log_sys->mutex 的争用路径。
-
innodb_log_file_size太小 → checkpoint 太频繁 → 脏页刷盘压力大 → 反向拖慢 log write 性能 - 但它增大后,并不会减少 mutex 抢占次数,甚至可能因单次刷盘量变大,延长后台 io_thread 工作时间,间接加重锁等待
- 真正该调的是
innodb_log_buffer_size:buffer 小 → 更容易满 → 更频繁 flush → 更多 mutex 争抢;观察Innodb_log_waits是否 > 0,持续增长就说明 buffer 不够用
哪些参数调整能直接减轻 log_sys 锁压力?
核心是让日志写入“绕过”或“缩短”对 mutex 的强依赖,同时接受对应的数据可靠性折衷。
-
innodb_flush_log_at_trx_commit = 2:日志写入 OS 缓存即返回,每秒由后台线程统一刷盘。吞吐可提升 3–10 倍,但崩溃最多丢 1 秒数据 -
innodb_log_buffer_size设为 64M(默认 16M):减少 buffer 溢出频率,降低 flush 触发次数,直接减少 mutex 抢占 - 避免在事务中做耗时操作(如远程调用、大字段拼接),缩短事务生命周期,也就缩短了 log 写入窗口
- 如果业务允许,
innodb_flush_log_at_trx_commit = 0更激进,但风险更高,仅限埋点、日志类非核心表
为什么你看到的“写入慢”常常不是磁盘问题?
很多运维第一反应是换更快的 SSD 或调大 I/O 调度器,但实际瓶颈在内存锁路径上——log_sys->mutex 是纯 CPU 竞争,跟磁盘延迟无关。即使换成 NVMe,只要锁没拆分,高并发下照样排队等。
真正容易被忽略的是:这个锁的争用在监控里不显眼,Innodb_os_log_pending_fsyncs 上升、Innodb_log_waits 持续非零、线程状态长期卡在 Writing to log,才是它在作祟的信号。别急着调磁盘参数,先看锁和 buffer。











