RHEL9等系统启动Mysql 5.7后,内存异常占用的问题

问题回顾

使用docker-compose.yaml启动了mysql容器。

启动成功后,使用free -mh查看宿主机内存占用情况,并用docket stats 查看容器情况,mysql竟然占用了16个G

docker-compose.yml

version: '3.1'

services:

  db:
    image: mysql:5.7
    ports:
     - "3310:3306"
    restart: always
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --init-connect='SET NAMES utf8mb4;' --innodb-flush-log-at-trx-commit=0
    environment:
      MYSQL_ROOT_PASSWORD: xxxxxxx
      MYSQL_DATABASE:xxxxxx
    volumes:
      - ./datadir:/var/lib/mysql:rw

原因分析

这个问题的直接原因是文件描述符上限太大了;

以前的很多软件在启动的时候都会有一些初始化的动作;
如关闭所有能关闭的文件描述符, 关闭所有能关闭的网络 socket 这一类的动作,
避免之前程序的干扰,或者是确认资源能使用;

但是早期版本的 linux 文件描述符上限, 默认一般是 1024, SA优化一般也就修改为 65535,
所以软件启动时很快就能执行完了, 说多也就1-2s; 也不会占用太多内存;

普通软件在未配置的情况也是继承操作系统的这个数值;

可是新版本的 kernel 和 el9+ 等新发行版把这个 系统级别的限制数值提高了非常多;
就导致很多传统软件在未适配的情况要么启动时CPU使用率极高, 要么启动时内存占用非常大;

这里应该是新版本的 containerd 自己单独修改的 ulimit 的上限导致的;
所以这个对容器单独进行资源限制解决了这个问题;

同时此问题未在 mysql 8.0+ 上出现, 猜测应该是程序自己有做优化;

ulimits:

nproc: 65535

nofile: soft: 26677

hard: 46677

重启容器然后正常了。

还有要提醒容器的系统太老了,都下不到最新软件包了。记得及时更新容器版本。