这个坑值得记一笔。订单表到两千万行后插入 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 也要相应放大。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
