现场是这样的。两核四 G 的实例上 MySQL 每隔两三天就消失一次,systemctl 显示服务已停止,业务侧报连接被拒绝,手动拉起后能撑一阵又复发。
原因不止一个,得分开看。物理内存只有四 G,缓冲池按默认值配到了接近一半,再加上 PHP 就超了;系统完全没有配交换分区,内存一紧张内核就直接挑占用最大的进程下手;容器限额和宿主机统计口径不一致,实际可用内存被高估。
先在内核日志里确认被杀的是哪个进程
dmesg -T | grep -i 'killed process'
然后看当时的内存与交换使用
free -h && vmstat 1 5
再往下把缓冲池压到实际内存的六成以内
grep -n innodb_buffer_pool_size /etc/my.cnf
降低关键进程被选中的概率
echo -500 > /proc/$(pidof mysqld)/oom_score_adj
怎么算真的好了,看的是同一批现象。连续运行一周不再出现被杀记录,数据库常驻内存稳定在实例规格之内,业务连接不再中断。
补一句。调大交换分区只是把崩溃往后推,缓冲池超过物理内存迟早还会被杀;用监控把峰值记下来比事后猜更可靠。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。