MySQL生产环境必须调优内存参数:innodb_buffer_pool_size按内存比例设置并留足系统空间,query_cache_type必须设为0,tmp_table_size与max_heap_table_size需相等,max_connections受ulimit限制且须配套调整thread_cache_size。

直接说结论:MySQL装完不能直接用默认配置跑生产,尤其内存参数——innodb_buffer_pool_size设太小会频繁刷盘,设太大可能触发 OOM;query_cache_type只要开了就拖慢并发,必须关;max_connections调高前得先看系统 ulimit -u 是否够用。
innodb_buffer_pool_size 怎么设才不翻车
这是唯一一个改错就能让查询慢几倍、甚至直接 OOM 的参数。它不是“越大越好”,而是要留足给 OS 和其他进程的空间。
- 4GB 以下内存机器(比如测试机、老 VPS):设成
512M~1G,别超 60% 总内存 - 4–16GB 内存:建议
2G~12G,按 60%~70% 算,比如 8GB 机器设innodb_buffer_pool_size = 5G - 32GB+ 专用数据库服务器:可到 75%~80%,但必须监控
innodb_buffer_pool_read_requests/innodb_buffer_pool_reads比值,>100:1 才算健康 - 如果 buffer pool >1GB,顺手加一句
innodb_buffer_pool_instances = 8,避免单实例锁争用
query_cache_type 必须设为 0
哪怕你每分钟只写一条数据,只要 query_cache_size > 0 且 query_cache_type = 1,MySQL 就得维护哈希表和互斥锁——这不是省资源,是主动制造瓶颈。
- MySQL 8.0 已彻底移除该功能,5.7 默认关闭,但很多安装包仍保留
query_cache_size = 1M这类残留配置 - 实操只做两件事:
query_cache_type = 0+query_cache_size = 0,一并注释掉或删掉也行 - 真要缓存,用 Redis 或 ProxySQL,粒度可控、不污染 MySQL 内存模型
tmp_table_size 和 max_heap_table_size 必须相等
这两个参数不一致,会导致 GROUP BY、ORDER BY、子查询等操作悄悄落到磁盘临时表,性能断崖下跌,而日志里还看不出明显报错。
- 设成一样:比如都设
tmp_table_size = 64M和max_heap_table_size = 64M - 监控指标是
Created_tmp_disk_tables/Created_tmp_tables,比值超过 10% 就说明内存临时表不够用 - 别盲目调大——每个连接都按这个值预分配内存,100 个连接就是 6.4GB,小内存机器扛不住
max_connections 超过 1024 就得查 ulimit
Cannot create thread 不是 MySQL 报的错,是 Linux 内核拒绝创建线程。CentOS/RHEL 默认 ulimit -u 是 1024,max_connections = 2000 就直接越界。
- 先执行
ulimit -u查当前限制,再决定max_connections能设多高 - 要调高,得改
/etc/security/limits.conf(比如加mysql soft nproc 4096),然后重启 mysqld - 同时配好
thread_cache_size,建议设成max_connections的 20%~30%,减少线程反复创建销毁开销
最常被忽略的点:所有涉及内存的参数(尤其是 innodb_buffer_pool_size、tmp_table_size)改完必须重启 MySQL 才生效;而像 sort_buffer_size 这类会话级参数,即使动态 set global,新连接也不会继承——得写进 my.cnf 的 [mysqld] 段里才真正落地。


















