mysql启动报“cannot allocate memory”时,应将innodb_buffer_pool_size设为物理内存的50%~70%,小内存(≤4gb)机器建议128m或256m,并关闭large_pages,修改后需重启生效。

mysql启动失败报 Cannot allocate memory 怎么调 innodb_buffer_pool_size
这是最常踩的坑:装完 MySQL 直接用默认配置跑在 2GB 或 4GB 内存的机器上,innodb_buffer_pool_size 默认可能设到 128MB 甚至更高,加上其他内存开销(连接线程、排序缓冲等),一启动就 OOM。
实操建议:
-
innodb_buffer_pool_size别超过物理内存的 50%~70%,小内存机器(≤4GB)建议直接设为128M或256M - 查当前值:
SELECT @@innodb_buffer_pool_size;,单位是字节,别被大数字吓到 - 修改前先确认 MySQL 是否启用了
large_pages(会额外占内存),没特殊需求就关掉:large_pages = OFF - 改完必须重启 MySQL 才生效,热修改不支持
查询变慢但 SHOW PROCESSLIST 没卡住,检查 sort_buffer_size 和 read_rnd_buffer_size
这类慢不是锁表或死锁,而是单条查询因临时内存不足被迫写磁盘排序,性能断崖式下跌。尤其在 ORDER BY + LIMIT 或多表 JOIN 后排序时明显。
实操建议:
-
sort_buffer_size是**每个连接独享**的,不是全局总和,设太高会导致并发连接数稍高就内存爆炸 - 普通应用设
256K~1M足够,除非你确定有大量复杂排序且并发很低 -
read_rnd_buffer_size控制排序后回表读行的批量大小,一般保持和sort_buffer_size同量级或略小 - 这两个参数在线动态设置有效(
SET SESSION sort_buffer_size = 524288;),适合临时诊断
为什么加了 query_cache_type = 1 反而更卡
Query Cache 在 MySQL 5.7 已废弃、8.0 直接移除,但在老版本(如 5.6)里开着它,高并发写入场景下会成为性能黑洞——每次更新表都要清空整个表相关的所有缓存,锁竞争剧烈。
实操建议:
- 只要业务有写操作(哪怕每分钟几条),就设
query_cache_type = 0彻底关闭 - 别信“我写得少”,只要
query_cache_size > 0且query_cache_type = 1,MySQL 就要维护缓存哈希表和互斥锁 - 替代方案是用应用层缓存(Redis)或代理层缓存(ProxySQL),粒度可控、不污染 MySQL 内存模型
max_connections 设太高导致系统报 Cannot create thread
不是 MySQL 自己报错,而是 Linux 内核拒绝创建新线程,常见于 CentOS/RHEL 默认 ulimit -u(用户进程数限制)只有 1024,而 max_connections = 2000 就越界了。
实操建议:
- 先查系统限制:
ulimit -u,再看 MySQL 实际用了多少线程:SHOW STATUS LIKE 'Threads_connected'; -
max_connections别盲目往高设,先看业务真实并发连接峰值(比如用pt-online-schema-change或监控工具抓 24 小时数据) - 如果真需要高连接数,必须同步调大系统限制:
/etc/security/limits.conf加mysql soft nproc 65535,并确认mysqld启动用户能生效 - 连接池(如 HikariCP)比硬抬
max_connections更靠谱,避免连接空转吃内存
真正难的不是记住哪几个参数,而是理解每个参数背后绑定的资源类型:有的占固定内存(innodb_buffer_pool_size),有的按连接倍增(sort_buffer_size),有的触发内核级限制(max_connections)。改之前,先用 ps aux --sort=-%mem | head -10 看看 mysqld 进程实际吃了多少内存,比拍脑袋调参可靠得多。











