增大InnoDB buffer pool size后CPU占用过高、数据库运行变慢求助
可能的诱发原因如下
Buffer Pool实例数配置不匹配
调大innodb_buffer_pool_size后如果没有同步调整innodb_buffer_pool_instances,会导致单个Buffer Pool实例过大,锁竞争急剧上升。InnoDB为每个Buffer Pool实例维护独立的LRU链表、互斥锁,单实例超过2G时,大量页操作都会争抢同一把锁,直接拉高CPU使用率,同时锁等待会拖慢查询执行速度。常规建议每个Buffer Pool实例大小控制在1G-2G区间,例如调整后总Buffer Pool为8G时,实例数应设置为4-8。触发Swap分区交换
若调大后的Buffer Pool大小超过服务器可用物理内存(需预留足够内存给操作系统、其他进程,以及MySQL的其他内存模块如连接栈、sort buffer、join buffer等),操作系统会触发Swap,将部分Buffer Pool内存页置换到磁盘上。InnoDB感知不到Swap存在,仍按内存逻辑操作这些页,会产生大量磁盘IO同时伴随极高的系统态CPU占用,直接拉低整体性能。LRU链表扫描开销陡增
Buffer Pool扩容后,InnoDB后台刷新线程、LRU淘汰线程需要扫描的链表长度大幅增加。如果innodb_lru_scan_depth配置仍为默认值甚至更高,每次扫描LRU链表查找可淘汰页的CPU开销会直线上升,尤其在写入量大的场景下,脏页刷新频率更高,这部分开销会被进一步放大。脏页刷新策略不匹配
Buffer Pool变大后可缓存的脏页数量同步提升,如果innodb_max_dirty_pages_pct阈值设置过高,会导致大量脏页累积到接近阈值时才触发批量刷新,瞬时的刷新操作会占用大量CPU和IO资源,同时阻塞用户查询,出现性能陡降的波动。MySQL 5.7及以上版本如果未开启innodb_adaptive_flushing,也会出现类似的批量刷新导致的性能问题。查询执行计划异常变动
Buffer Pool扩容后,优化器估算的索引扫描成本会降低,可能会选择范围扫描代替原来的小表全表扫描,甚至选错索引。如果业务存在大量未加索引的查询、或者索引区分度低,这种执行计划的变动可能会导致大量数据页被加载到Buffer Pool,同时伴随大量CPU计算,反而拉低整体性能,可通过explain核对慢查询的执行计划是否有异常。
内容的提问来源于stack exchange,提问作者Bhans345

