适用场景: Kylin V10 系统 + Docker 容器部署 MySQL
问题类别: 容器文件描述符限制异常
一、问题描述
在 Kylin V10 系统上通过 Docker 容器部署 MySQL 时,发现以下异常现象:
- 直接在 MySQL 中修改
open_files_limit参数的值不生效 - MySQL 容器重启后,
open_files_limit参数会被重置为异常值
说明:
open_files_limit的取值与 ulimit 设定的open files参数直接相关,表现为 Kylin V10 存在 MySQL 方面的兼容性问题。
1.1 各环境实测对比
| 环境 | 主机 open files 值 | 容器 open files 值 | 状态 |
|---|---|---|---|
| Kylin V10 | 100001 | 1073741816 | ⚠ 异常(过大) |
| CentOS 等其他系统 | 65535 | 1048576 | ✅ 正常 |
二、原因分析
2.1 Linux 文件描述符限制机制
Linux 系统通过以下方式限制打开文件的数量(nofile):
- 配置文件:
/etc/security/limits.conf - 查看命令:
ulimit -a中的open files项
2.2 Docker 与宿主机的隔离关系
⚠️ 重要: Docker 对打开文件数量(nofile)的限制与 Linux 系统的限制完全隔离!
Docker 守护进程通过 docker.service 文件中的 LimitNOFILE 参数独立管理容器的文件描述符上限,与宿主机 /etc/security/limits.conf 的配置互不影响。
2.3 Kylin V10 特殊性分析
问题根因在于 docker.service 文件中使用了 LimitNOFILE=infinity 默认配置:
| 操作系统 | LimitNOFILE=infinity 换算值 |
备注 |
|---|---|---|
| Kylin V10 | 1073741816(约 2³⁰) | 系统特性导致换算异常 |
| CentOS / Ubuntu 等 | 1048576(约 2²⁰) | 标准换算结果 |
由于 Kylin V10 对 infinity 的换算方式与其他操作系统不同,导致容器内 open_files_limit 取值远超预期,进而引发 MySQL 参数异常。
三、解决方案
将 docker.service 中的 LimitNOFILE 由 infinity 改为明确数值 1048576,与其他主流操作系统行为保持一致。
步骤 1:定位 docker.service 文件
# 查找 docker.service 文件位置
systemctl show docker | grep FragmentPath# 常见路径(任选其一)
# /usr/lib/systemd/system/docker.service
# /lib/systemd/system/docker.service
# /etc/systemd/system/docker.service
步骤 2:编辑 docker.service 文件
# 使用编辑器打开文件(以 vim 为例)
vim /usr/lib/systemd/system/docker.service# 找到 [Service] 节,修改以下参数:
# 将:LimitNOFILE=infinity
# 改为:LimitNOFILE=1048576
步骤 3:重载并重启 Docker
# 重载 systemd 配置并重启 Docker 服务
systemctl daemon-reload && systemctl restart docker
步骤 4:验证修改结果
# 验证宿主机 open files 值
ulimit -a | grep 'open files'# 进入 MySQL 容器验证(将 <container_id> 替换为实际容器 ID)
docker exec -it <container_id> bash
ulimit -a | grep 'open files'# 在 MySQL 中验证参数
mysql -u root -p
SHOW VARIABLES LIKE 'open_files_limit';
四、验证标准
| 验证项 | 预期结果 | 验证方式 |
|---|---|---|
| 容器 open files 值 | 1048576 | 容器内 ulimit -a |
| MySQL open_files_limit | 与 open files 值一致 | MySQL SHOW VARIABLES |
| 容器重启后参数保持 | 重启后不被重置 | 重启容器后再次验证 |
| Docker 服务状态 | 正常运行 | systemctl status docker |
五、注意事项
⚠️ 修改
docker.service文件后必须执行daemon-reload,否则修改不会生效;重启 Docker 将导致所有容器短暂停止服务,请在维护窗口内操作。
- 本方案适用于使用 systemd 管理 Docker 的 Kylin V10 环境
- 修改后若业务对文件描述符有更高需求,可适当调大
LimitNOFILE的值 - 操作前建议备份原始文件:
cp /usr/lib/systemd/system/docker.service ~/docker.service.bak - 若环境中存在多个
docker.service文件(如/etc/systemd/system/覆盖),需同步修改所有生效文件
六、相关背景知识
6.1 open_files_limit 参数说明
MySQL 的 open_files_limit 参数用于控制操作系统允许 MySQL 进程打开的文件数量上限。该值受操作系统(或容器)的 ulimit open files 限制,无法在 MySQL 层面单独超越该上限进行设置。
6.2 Linux nofile 与 Docker nofile 的关系
| 配置层 | 配置项 | 配置位置 | 影响范围 |
|---|---|---|---|
| 操作系统 | nofile(open files) | /etc/security/limits.conf |
宿主机进程 |
| Docker 守护进程 | LimitNOFILE | docker.service |
所有 Docker 容器 |
| 单个容器(可选) | --ulimit nofile |
docker run 参数 |
指定容器 |
附录:快速操作脚本
以下脚本可一键完成 docker.service 修改与服务重启,请在确认备份后执行:
#!/bin/bash
# MySQL open_files_limit 修复脚本
# 适用于 Kylin V10 + Docker 环境SERVICE_FILE=$(systemctl show docker | grep FragmentPath | cut -d= -f2)
echo "Docker service 文件路径: $SERVICE_FILE"# 备份原始文件
cp "$SERVICE_FILE" "${SERVICE_FILE}.bak"
echo "已备份至: ${SERVICE_FILE}.bak"# 修改 LimitNOFILE
sed -i 's/LimitNOFILE=infinity/LimitNOFILE=1048576/' "$SERVICE_FILE"# 重载并重启
systemctl daemon-reload && systemctl restart docker
echo "Docker 已重启,open files 上限已修正为 1048576"
如仍存在问题,请检查是否有其他
docker.service覆盖文件(/etc/systemd/system/docker.service),并同步修改。
