卡在INSERT语句上首要检查innodb_buffer_pool_size是否过小,生产建议设为物理内存50%–75%,并验证Buffer pool hit rate是否持续≥990/1000。

写入卡在 INSERT 语句上,先看是不是缓冲池太小
InnoDB 的 innodb_buffer_pool_size 直接决定多少数据和索引能常驻内存。如果它只设了 128MB,而你的表总大小 2GB,每次写入都得频繁刷脏页、读磁盘页,INSERT 就会卡住——不是 SQL 写得慢,是底层反复等 IO。
- 生产环境建议设为物理内存的 50%–75%,但别超过 80%,留内存给 OS 和其他进程
- 动态调整可用
SET GLOBAL innodb_buffer_pool_size = 2147483648;(需 MySQL 5.7.5+,且innodb_buffer_pool_instances要匹配,否则无效) - 改完立刻查
SHOW ENGINE INNODB STATUS\G,重点关注 “Buffer pool hit rate” —— 持续低于 990/1000 就说明还是不够用
innodb_flush_log_at_trx_commit=1 导致每条事务都刷盘,要不要关?
默认值 1 是 ACID 安全底线:每次 COMMIT 都强制把 redo log 写入并刷到磁盘。关成 0 或 2 确实能提速,但代价是崩溃可能丢一秒事务(0)或最多丢一秒钟日志(2)。
- 仅在明确接受数据丢失风险的场景下调,比如日志表、中间计算表
-
2是折中选择:log 写入 OS 缓存即返回,由 OS 每秒刷一次,实际丢数据概率低,性能提升明显 - 千万别只改这个参数就上线——要同步确认
sync_binlog设置,否则主从不一致风险陡增
大批量写入时 INSERT ... VALUES (),(),() 比循环单条快多少?
单条 INSERT 触发完整事务开销(加锁、日志写入、刷盘),而批量插入能把多行压进一次事务、一次日志刷写,吞吐量通常提升 3–10 倍,尤其在 SSD 上更明显。
- 单次插入行数控制在 1000 行以内,再大容易触发
max_allowed_packet错误或锁等待加剧 - 配合
START TRANSACTION+ 批量INSERT+COMMIT,比自动提交快得多 - 如果用 ORM,确认它没偷偷拆成单条执行;有些框架对批量支持弱,得手动拼 SQL 或换批量接口
磁盘 IO 真瓶颈了,innodb_io_capacity 和 innodb_io_capacity_max 怎么设?
这两个参数告诉 InnoDB 磁盘有多快,影响后台刷脏页、合并 change buffer 的节奏。设太低,IO 闲置;设太高,刷得太猛挤占前台写入带宽,反而卡住。
- 普通 SATA SSD:设
innodb_io_capacity = 200,innodb_io_capacity_max = 2000 - NVMe SSD:可设到
2000/4000,但必须用iostat -x 1实测真实 IOPS 和 await 值来反推 - 切记:这些值只在
innodb_adaptive_flushing = ON时生效,老版本默认 OFF,得手动打开
真正卡顿往往不是单点参数问题,而是缓冲池、日志刷盘策略、SQL 写法、磁盘能力四者没对齐。调参前务必用 pt-query-digest 看慢查询分布,用 iostat 看 await 和 %util,否则容易把 CPU 等待当成 IO 卡顿。



















