应通过watch -n 2 'ps -o pid,user,%mem,rss,vsz,comm -C mysqld'查看RSS值(KB),结合free -h的available列判断真实内存占用,若RSS长期超innodb_buffer_pool_size + 1024MB即过载。

怎么看 MySQL 到底占了多少真实内存
宝塔面板的数据库列表页只显示“运行中”,不反映 mysqld 进程实际占用的物理内存。你得绕出去看 RSS(Resident Set Size)——这才是真正吃掉的内存。
执行这条命令,每 2 秒刷新一次:
watch -n 2 'ps -o pid,user,%mem,rss,vsz,comm -C mysqld'重点关注
RSS 列(单位 KB),如果长期超过 innodb_buffer_pool_size + 1024MB,基本就是过载了。
顺手再跑:
free -h看
available 列,不是 total 或 free ——这个值才是 MySQL 能安全用的上限基准。
为什么改了 innodb_buffer_pool_size 还爆内存
根本原因常是参数叠加超限:单个连接也会消耗内存(sort_buffer_size、join_buffer_size、tmp_table_size 等),而 max_connections 设太高时,哪怕大部分连接空闲,MySQL 也会为每个预留基础缓冲区。
-
innodb_buffer_pool_size应设为available内存的 50%~60%,不是总内存的 70% -
max_connections建议调到 64~128(小内存机器别留默认 151 或 200) -
tmp_table_size和max_heap_table_size必须设成同一值,推荐 64M - MySQL 8.0 已移除查询缓存,若用的是 5.7 且启用了
query_cache_type,务必注释掉整行
改完必须在宝塔面板【配置修改】里保存并【重启 MySQL】——直接改服务器上的 /www/server/mysql/etc/my.cnf 可能被宝塔自动覆盖。
怎么确认是不是其他进程在抢内存
MySQL 经常被当成“背锅侠”。先查系统级真实压力:
ps aux --sort=-%mem | head -n 10看前 10 名里有没有非必要的 Python 脚本、Node.js 服务、日志分析工具或未关闭的调试进程。
常见干扰项:
- 阿里云盾(
aliyun-service)在低配机器上可能吃掉 300MB+ - 多个 PHP 版本共存但只用一个,其余版本的
php-fpm进程仍在运行 - 宝塔计划任务里误设了每分钟执行的内存清理脚本,反而持续 fork 新进程
找到可疑 PID 后,用 kill -9 PID 结束,再执行 swapoff -a && swapon -a 清理交换分区状态(尤其当 Swap 曾被频繁使用过)。
要不要加 Swap?加多少合适
物理内存 ≤2GB 的云服务器,没 Swap 就像没刹车——OOM Killer 会直接杀 mysqld。但 Swap 不是万能补丁,只是给 MySQL 多一次喘息机会。
操作步骤(以 2GB Swap 为例):
- 执行
swapon --show确认当前未启用 -
fallocate -l 2G /swapfile(比dd更快更稳) chmod 600 /swapfile && mkswap /swapfile && swapon /swapfileecho '/swapfile none swap sw 0 0' >> /etc/fstab
注意:Swap 文件不能放在宝塔默认挂载的 /www 分区下(该分区常为 ext4 + noatime,但部分云厂商镜像对 Swap 支持不稳),优先放根分区。
真正难处理的,是那些连接数波动大、查询临时表多、又没开慢日志的应用——这时候光调参数没用,得去 SHOW FULL PROCESSLIST 里抓正在跑的 SQL,再结合 EXPLAIN 看执行计划。参数只是兜底,代码才是源头。


















