这个坑值得记一笔。订单表到两千万行后插入 QPS 从八千掉到三千,iostat 里写放大明显,InnoDB 的脏页比例长期在八成以上,机器是十六 G 内存。

刚开始盯着「主键不是自增,随机插入导致页分裂」,折腾了半个多小时,排掉了。

把日志和配置对完,能解释这个现象的基本就这几处。buffer pool 太小,脏页被频繁刷出;二级索引建得太多,每次写入要维护好几份;redo log 太小,检查点触发太频繁。

上来先看脏页比例和刷盘速度

mysql -e "show engine innodb status\G" | grep -A 5 'BUFFER POOL'

然后按内存调整 buffer pool 大小

mysql -e "set global innodb_buffer_pool_size=8589934592;"

接着列出索引看是否有冗余

mysql -e "select table_name,index_name,seq_in_index,column_name from information_schema.statistics where table_schema='shop' order by table_name;" | head -30

复核脏页比例与写入 QPS

mysql -e "show global status like 'Innodb_buffer_pool_pages_dirty';"

这类问题以前遇到过,但这次的触发条件和上次不一样。

怎么算真的好了,看的是同一批现象。脏页比例降到三成以下,插入 QPS 回到六千以上,iostat 里的写放大从四倍降到两倍以内。

写入变慢多数是刷脏跟不上,不是磁盘不行;buffer pool 一般给到物理内存的六成,redo 也要相应放大。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189