能提速,但代价是可能丢数据——只要宕机就一定丢;0每秒fsync、2仅write不fsync、1每次commit都fsync,三者性能与安全性逐级递增。

innodb_flush_log_at_trx_commit 设为 0/2 真的能提速?
能,但代价是可能丢数据——不是“大概率”,而是“只要宕机就一定丢”。这个参数控制的是事务提交时 redo log 的刷盘行为,不是开关,是策略选择。
常见错误现象:INSERT 批量插入时每条都 fsync(),磁盘 I/O 成瓶颈,QPS 上不去;调成 0 后吞吐翻倍,但机器断电后最近 1 秒事务全丢。
-
1(默认):每次COMMIT都写日志并fsync到磁盘 → 安全,慢 -
0:每秒一次fsync,事务只写入log buffer→ 快,但崩溃丢失最多 1 秒数据 -
2:每次COMMIT写入系统缓存(write()),不fsync→ 比1快,比0稍安全(进程崩溃不丢,OS 崩溃可能丢)
批量插入时,光调 innodb_flush_log_at_trx_commit 不够
这个参数只解决日志刷盘开销,但真正卡住插入性能的,往往是单条 INSERT + 自动提交、唯一索引校验、二级索引维护这些环节。
使用场景:导入日志、ETL 中间表、埋点数据入库等允许少量丢失或可重跑的场景。
- 务必关闭自动提交:
SET autocommit = 0,然后手动COMMIT多条语句 - 用
INSERT INTO ... VALUES (...), (...), (...)批量值,别写 N 条单行INSERT - 临时禁用唯一约束检查(仅限可信数据):
SET unique_checks = 0,导入完再开 - 如果表无主键或二级索引,插入会快很多——但生产环境几乎不可能这么干
为什么设成 2 还是慢?查查 sync_binlog
MySQL 开启了 binlog(比如用了主从复制),那 innodb_flush_log_at_trx_commit = 2 就不够了——因为 sync_binlog 也在抢磁盘。
错误现象:调了 innodb_flush_log_at_trx_commit = 2,但 INSERT 延迟还是高,iostat -x 1 显示 %util 持续 100%。
-
sync_binlog = 1(默认):每次事务都fsyncbinlog → 和innodb_flush_log_at_trx_commit = 1叠加,双重落盘 - 可设为
0(依赖 OS 刷盘)或1000(每 1000 次事务刷一次)→ 提速明显,但主从延迟和崩溃丢 binlog 风险上升 - 注意:
sync_binlog = 0+innodb_flush_log_at_trx_commit = 2是常见折中组合,适用于对主从一致性要求不苛刻的写密集型业务
SSD 上调大 innodb_log_file_size 有帮助吗?
有,但不是直接加速单次插入,而是减少 redo log checkpoint 频率,让后台刷脏页更平滑,避免突发 I/O 尖峰拖慢插入。
参数差异:innodb_log_file_size 是每个 log file 的大小(如 ib_logfile0),总容量是 innodb_log_files_in_group × innodb_log_file_size。默认通常 48MB,太小。
- 建议总 redo log 容量设为 1–2GB(例如 2 × 1G),具体看写入峰值 QPS 和平均事务大小
- 修改需停库:先
SET GLOBAL innodb_fast_shutdown = 0,关 MySQL,删旧ib_logfile*,改配置,再启动 - 改太大会延长崩溃恢复时间;改太小会导致频繁 checkpoint,
Innodb_os_log_written监控值跳变剧烈
真正决定插入上限的,从来不是某一个参数,而是日志刷盘、缓冲区竞争、索引维护、磁盘带宽这四层叠加的瓶颈。调 innodb_flush_log_at_trx_commit 是最立竿见影的切口,但漏掉 sync_binlog 或不会批量提交,等于只拧松一颗螺丝就指望整台发动机提速。











