CentOS 7.9 上 MySQL 8.0.32,8 核 16G,innodb_buffer_pool_size 给了 8G,每次发版重启后十分钟内接口大面积超时,iostat 里读 IOPS 打满,过了这段时间自己就好了。

排查方向其实有限,先把可能性排一排。热数据全在内存里,重启后缓冲池是空的,前几万次查询全部落到磁盘随机读;关闭时导出的页映射文件没有正常生成,启动时无东西可加载,只能靠业务慢慢把缓存填回来;buffer pool 分成多个实例,预热线程数默认偏少,8G 要读很久;重启后一批定时任务同时开跑,把仅有的缓存又挤了出去。

动手时先确认导出文件是否存在以及大小

ls -lh /var/lib/mysql/ib_buffer_pool

接着打开关闭时导出、启动时加载这两个开关

mysql -e 'set global innodb_buffer_pool_dump_at_shutdown=ON; set global innodb_buffer_pool_load_at_startup=ON;'

立刻手工触发一次预热并看进度

mysql -e 'set global innodb_buffer_pool_dump_now=ON; set global innodb_buffer_pool_load_now=ON; show status like "Innodb_buffer_pool_load_status";'

末了观察命中率是否回到常态

mysql -e 'show global status like "Innodb_buffer_pool_read_requests"; show global status like "Innodb_buffer_pool_reads";'

别只看报错消失,验证要多做一步。重启后三分钟内缓冲池加载状态显示完成,命中率在百分之九十九以上,iostat 的读 IOPS 不再打满,接口响应与重启前一致。

预热只解决读,写多的库还要看 redo 与刷盘策略;导出文件要跟着实例走,容器重建后路径挂错就等于没开。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189