MySQL启动即占大量内存主因是innodb_buffer_pool_size预分配和open_files_limit在Kylin V10上被内核错误放大至十亿级;前者需确保≤available内存减2GB且新值须为chunk×instances整数倍,后者需容器启动时--ulimit限制或my.cnf显式设65536。

MySQL 启动后立即占用大量内存,不是 bug,是它按配置“照单全收”地预分配——尤其是 innodb_buffer_pool_size 和 open_files_limit 这两个参数,一个锁死整块内存不释放,一个在 Kylin V10 等系统上被内核错误放大到十亿级,直接触发 GB 级预分配。
innodb_buffer_pool_size 是内存杀手,不是缓存开关
这个参数不是“用多少分多少”,而是 MySQL 启动时就向 OS 申请一块固定大小的连续内存。哪怕你只执行一条 SELECT 1,它也占着不动。
- 查实际值:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size',注意单位是字节;free -h看available列,别看free—— buffer pool 必须 ≤ 这个值再减去 2GB(给 OS、agent、容器 runtime 留余量) - 动态调小会重建整个 buffer pool,期间可能卡顿;新值必须是
innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances的整数倍,否则会被向下取整(调完立刻SHOW VARIABLES确认生效值) - 禁用
innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup:热数据远小于 buffer pool 时,加载过程反而拖慢启动、多占 I/O 缓存
open_files_limit 在 Kylin V10 上会引发内存雪崩
这不是 MySQL 配置问题,是 Kylin V10 内核 + Docker 默认配置的兼容性缺陷:MySQL 读取 /proc/self/limits 时拿到一个异常高的 Max open files(比如 1073741816),于是按此值预分配文件句柄管理结构,内存直接飙到 16GB+。
- 验证方法:进容器执行
cat /proc/self/limits | grep "Max open files",若第二列(soft limit)接近 10 亿,基本就是它 - 修复方案一(推荐):启动容器时加
--ulimit nofile=65536:65536,强制限制句柄数 - 修复方案二:在
my.cnf中显式设open_files_limit = 65536(注意:仅当 MySQL 有 root 权限时才生效,容器里通常不满足)
每个连接都在偷偷吃内存,Sleep 状态最危险
一个空闲的 Sleep 连接仍独占 thread_stack(默认 256KB–2MB)、sort_buffer_size、join_buffer_size 等。1000 个 Sleep 连接轻松吞掉 2GB+。
- 查真实连接数:
SHOW STATUS LIKE 'Threads_connected',对比max_connections;若长期 >70% 且SHOW PROCESSLIST里大量Sleep,说明应用没释放连接 - 收紧保活时间:
wait_timeout = 300、interactive_timeout = 300(单位秒),避免连接堆积 - 检查应用层:Java 用 HikariCP 要开
leak-detection-threshold;PHP 避免未配 persistent 却复用 mysql_connect()
真正难处理的是那种“看起来都调对了,但内存还是下不来”的情况——大概率是 Kylin V10 的 open_files_limit 隐形放大,或者 buffer pool 实际生效值被 chunk 对齐规则悄悄截断,而你没去 SHOW VARIABLES 确认。


















