MySQL 8.0 跑在 16G 的机器上,缓冲池给了 8G,ps 里 mysqld 的 RSS 却涨到 12G,free 只剩一 G 多,重启后几天又慢慢涨回去,怀疑是内存泄漏。
一开始怀疑是「每个连接的读缓冲、排序缓冲按需分配,连接数多时叠加起来很可观」,查了一圈,方向不对。
排查方向其实有限,先把可能性排一排。performance_schema 默认开启,语句历史与阶段事件在内存里保留大量行。也可能是监控库每分钟拉一次全量指标,历史表被反复写入又没人清理。
还有一种情况,内存分配器释放后不立刻还给操作系统,RSS 看着只涨不降。
上来先看内存都被哪些组件占了
mysql -e 'select event_name,current_alloc from sys.memory_global_by_current_bytes limit 10;'
然后关掉不需要的历史事件采集
mysql -e 'update performance_schema.setup_consumers set enabled="NO" where name like "events_statements_history%";'
随后核对连接相关的缓冲参数
mysql -e 'show variables like "%buffer_size";'
隔一天再看 RSS 是否回落
ps -o rss= -p $(pidof mysqld) | awk '{print $1/1024 " MB"}'
改完先别撤,确认这几项。mysqld 的 RSS 稳定在十 G 以内不再持续上涨,free 保留两 G 以上余量,慢查询与连接错误都没有增加。
容易忽略的是,RSS 不回落不等于泄漏,要看 sys 库里的实时分配;关采集会影响诊断能力,按需取舍而不是一律关掉。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
