mysql写入变慢主因是磁盘io或innodb日志刷盘机制问题,应优先用iotop -op查mysqld刷盘、iostat -x看磁盘延迟,再检查innodb_flush_log_at_trx_commit与sync_binlog组合配置及innodb_log_file_size是否过小,并排查raid缓存失效或云盘iops耗尽等硬件层因素。

不是SQL写得差,也不是索引没建好——90% 的突发写入变慢,根子在磁盘IO或InnoDB日志刷盘机制上。
先看是不是 mysqld 在疯狂刷盘
别急着改SQL或加索引。直接运行 iotop -oP,盯住 mysqld 进程的 WRITE 列:如果持续 >10MB/s 且伴随高延迟,说明它正在被日志或脏页刷新拖住。
- 常见现象:
SHOW PROCESSLIST里一堆Writing to net或Updating卡住,但SELECT没事 - 关键指标:
Innodb_os_log_written每秒突增(SHOW GLOBAL STATUS LIKE 'Innodb_os_log_written'),而Threads_running并不高 - 别信 top 的 CPU 占用率——
iostat -x 1才是真相:若%util>80% 或await>10ms(SSD)/ >30ms(HDD),就是磁盘扛不住了
检查 innodb_flush_log_at_trx_commit 和 sync_binlog 是否被悄悄改过
这两个参数一松一紧,组合错就直接让写入掉速。尤其注意运维脚本、备份工具或云平台控制台是否自动重置过它们。
-
innodb_flush_log_at_trx_commit = 1+sync_binlog = 1:最安全,但每次事务都 fsync,IO压力最大 -
innodb_flush_log_at_trx_commit = 2+sync_binlog = 0:写入快,但崩溃可能丢最多1秒数据 + 主从不一致风险 - 危险组合:
innodb_flush_log_at_trx_commit = 2但sync_binlog = 1——事务提交时仍被 binlog 的 fsync 卡住,速度卡在中间档 - 查当前值:
SELECT @@innodb_flush_log_at_trx_commit, @@sync_binlog;
innodb_log_file_size 太小会导致周期性卡顿
不是一直慢,而是每1–3分钟突然卡一下?大概率是 redo log 循环写太频繁,把后台刷脏页任务推到了前台事务里。
- 验证方法:
SHOW ENGINE INNODB STATUS\G看 LOG 部分:Log sequence number和Last checkpoint at差距极小(比如只差几MB) - 计算建议值:用
Innodb_os_log_written除以 3600,得出每秒平均日志量,乘以 3600 得到 1 小时写入量 → 至少设为该值的 1.5 倍 - 常见误设:还用默认
48M,实际应设为1G–4G;调整需停库,不能在线改
别忽略 RAID 卡缓存和云盘 IOPS 爆仓
硬件层的问题最容易被当成数据库问题。尤其在物理机或私有云环境,RAID卡电池失效或云盘突发配额耗尽,会无声无息地让写入降速。
- RAID卡:用
megasasctl -AdpAllInfo(LSI卡)或storcli /c0 show查 write cache 是否启用;电池失效时,write back 自动降级为 write through,日志写变同步阻塞 - 云盘(如阿里云 ESSD):查监控里 IOPS 使用率是否长期 100%,burst 模式耗尽后会强制限速,且不会报错,只变慢
- 机械盘(HDD):
innodb_flush_method = O_DIRECT可能更差,反而关掉更稳;SSD 才真正受益
真正难排查的,往往不是参数设错,而是多个条件叠加:比如 innodb_log_file_size 偏小 + 业务高峰 + 云盘 burst 耗尽,三者同时触发才显出症状。单看任一指标都“还在合理范围”,合起来就卡死。











