MySQL 8.0升级后OOM的根本原因是innodb_buffer_pool_size默认按内存自动推导且存在chunk对齐机制,叠加performance_schema全开预占内存,需同时配置chunk_size、instances、关闭P_S高耗consumer并禁用buffer_pool_load_at_startup。
根本不是“新版本更吃内存”,而是innodb_buffer_pool_size默认行为从“保守固定值”变成“按物理内存自动推导”,再叠加performance_schema全开,默认吃掉300–500MB,两者一碰就超4G机器的可用内存边界。你看到SHOW VARIABLES里是1G,实际RSS可能飙到3.2G——因为InnoDB向上对齐分配,且events_statements_history_long等表启动即占128MB+。
MySQL 8.0.22+会动态算innodb_buffer_pool_chunk_size,若你没显式设,它可能算出256MB chunk × 8 instances = 2GB,哪怕你配了innodb_buffer_pool_size = 1280M,也会被强制对齐到2GB。结果就是配置失效、OOM照旧。
my.cnf中同时写死:innodb_buffer_pool_chunk_size = 128M(推荐,1M整数倍)innodb_buffer_pool_instances,确保innodb_buffer_pool_size / (128 * 1024 * 1024 * innodb_buffer_pool_instances)是整数(例如设1280M,instances只能选2或4或8)ib_logfile0和ib_logfile1(路径通常是/www/server/data/或/var/lib/mysql/),否则启动报错它不是“可选插件”,而是默认全开、启动即预分配内存的重量级组件。重点关掉两个最耗内存的consumer:
UPDATE performance_schema.setup_consumers SET ENABLED = 'NO' WHERE NAME IN ('events_statements_history_long', 'events_transactions_history_long');
my.cnf里加两行限制大小:performance_schema_events_statements_history_long_size = 10000(默认20000),performance_schema_events_transactions_history_long_size = 10000
SELECT * FROM performance_schema.memory_summary_global_by_event_name WHERE event_name LIKE 'memory/performance_schema/%' ORDER BY SUM_ALLOCATED DESC LIMIT 5;
MySQL 8.0默认开启innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup。重启后几秒内RSS陡增,不是泄漏,是后台线程疯狂加载上次dump的ib_buffer_pool文件——如果这文件有800MB,而你只配了1G buffer pool,它照样硬塞。
SET GLOBAL innodb_buffer_pool_load_at_startup = OFF;
my.cnf中加innodb_buffer_pool_load_at_startup = OFF
innodb_buffer_pool_dump_pct = 10(默认25)ib_buffer_pool文件(同数据目录下),避免残留大文件干扰真正卡点不在参数名本身,而在“chunk size × instances”必须整除你写的buffer pool size,以及P_S consumer关闭必须落地到SQL+配置双生效——少一步,OOM就还在门口等着。