innodb_flush_log_at_trx_commit=1压垮磁盘i/o是因为每次事务提交强制fsync,高并发下等效于每秒上千次串行磁盘写,导致%util达100%、await飙升;设为2可提升吞吐3–10倍,但崩溃时最多丢失1秒事务,仅适用于日志等可丢数据场景,资金类业务严禁使用。

因为 innodb_flush_log_at_trx_commit=1 强制每次事务提交都调用 fsync(),在高并发下等价于把写入变成串行磁盘操作——这不是配置没调好,是它本来就这样设计。
为什么设为 1 就会压垮磁盘 I/O
每秒上千事务提交,就等于每秒触发上千次 fsync()。SSD 单次延迟通常 0.3–1ms,HDD 可达 5–15ms;iostat 看到 %util 长期 100%、await > 50ms,但 svctm 很低(说明不是磁盘慢,是 fsync 在排队)。SHOW ENGINE INNODB STATUS 里 Log flushed up to 明显滞后于 Log sequence number,差值持续扩大,就是典型信号。
设成 2 真的能缓解?风险在哪
能缓解,吞吐通常提升 3–10 倍,但只适用于明确接受“最多丢失 1 秒已提交事务”的场景:
- 日志表、埋点数据、非核心状态更新可用
- 资金、订单、账户类业务绝对不能用——哪怕只有一张表涉及余额变更
-
innodb_flush_log_at_trx_commit=2搭配sync_binlog=1会导致 binlog 和 redo log 不一致,主从复制可能中断 - OS crash 或断电时,最近 1 秒事务可能丢失;MySQL 进程 crash 不丢
binlog 写入慢,光调 innodb_flush_log_at_trx_commit 没用
开启 binlog 后,sync_binlog=1 + innodb_flush_log_at_trx_commit=1 实际触发两次 fsync:一次写 redo,一次写 binlog。单纯调低前者,binlog 还卡在 Writing to binlog 状态。
真正要协同的是:
-
sync_binlog=1000:让 binlog 每 1000 个事务刷一次,I/O 下降 99% -
binlog_group_commit_sync_delay=100(单位微秒)+binlog_group_commit_sync_no_delay_count=10:避免“凑不够组就干等” - 观察
SHOW STATUS LIKE 'Binlog_group_commit%'中Binlog_group_commit_trigger_count是否明显高于Binlog_group_commit_trigger_timeout,确认 delay 起效
容易被忽略的硬件与路径细节
innodb_log_group_home_dir 只控制 ib_logfile0/1 存放位置,和你的业务日志表物理存储无关。把它挪到高速盘对写入性能提升微乎其微。
真正该动的是业务表的物理位置:
- 新建专用表空间:
CREATE TABLESPACE log_ts ADD DATAFILE '/data/logdisk/log_ts.ibd' ENGINE=InnoDB - 迁移表:
ALTER TABLE app_log TABLESPACE log_ts - 验证:
SELECT FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE TABLE_NAME='app_log' - 注意:MySQL 5.7.6+ 才支持,且表不能有全文索引或虚拟列;迁移过程锁表,权限和挂载点可写性必须提前确认











