Docker部署达梦数据库(DM8)常见问题排查实战(OOM、权限拒绝、数据持久化)

1. 背景与问题现象

在使用Docker部署达梦数据库(DM8)的过程中,容器启动后数据库服务未能正常运行,查看容器日志(docker logs)时发现以下核心报错:

Can not create buffer pools, out of memory!

同时,该容器内已经存在重要的业务数据,但在初次创建时未进行数据卷挂载。本文记录了从保障数据安全到解决内存溢出及权限问题的完整排查与重建过程。

2. 排查与解决过程

第一步:数据安全与持久化挂载

由于旧容器未挂载数据卷,直接删除会导致数据丢失。为了实现数据的持久化,需要将容器内数据拷贝至宿主机。
1. 检查容器挂载信息:

docker inspect -f '{{ range .Mounts }}{{ .Source }} -> {{ .Destination }}{{ println }}{{ end }}' dm8-new

若输出为空,说明数据全在容器内部。
2. 将数据拷贝到宿主机:

mkdir -p /mnt/home/dm8-new
docker cp dm8-new:/opt/dmdbms/data /mnt/home/dm8-new/data

确认数据大小无误(du -sh /mnt/home/dm8-new/data)后,安全删除旧容器:

docker rm dm8-new

第二步:重建容器并解决权限拒绝问题

使用挂载目录的方式重新创建容器,并扩大Docker共享内存:

docker run -d \
  --name dm8-new \
  -p 5236:5236 \
  --shm-size=4g \
  -v /mnt/home/dm8-new/data:/opt/dmdbms/data \
  dm-docker-dm8:latest \
  /opt/entrypoint.sh

启动后发现日志报错 Permission denied:

os_file_open_normal_rw error! path: '/opt/dmdbms/data/DAMENG/dm.ctl', code: 13, desc: Permission denied

原因分析: docker cp 拷贝出来的文件保留了容器内 dmdba 用户的UID,新容器内进程访问宿主机挂载文件时权限不匹配。
解决方案: 修改宿主机挂载目录的权限(推荐使用 chown 精确匹配UID,测试环境可使用 chmod 快速放权):

chmod -R 777 /mnt/home/dm8-new/data
docker restart dm8-new

第三步:解决内存溢出(OOM)问题

权限解决后,日志再次报出初始的 out of memory 错误。这是由于达梦数据库默认的内存配置过高,超出了容器分配的资源上限。
解决方案: 直接在宿主机修改挂载出来的 dm.ini 配置文件,强制指定较小的内存池。

vi /mnt/home/dm8-new/data/DAMENG/dm.ini

在文件末尾添加以下内存限制参数(按 Esc -> Shift + g 跳至末尾 -> o 新建一行编辑):

MEMORY_POOL = 500
BUFFER = 1000
MAX_BUFFER = 2000
RECYCLE = 64
HJ_BUF_GLOBAL_SIZE = 500
HJ_BUF_SIZE = 50
HAGR_BUF_GLOBAL_SIZE = 500
HAGR_BUF_SIZE = 50

保存退出(:wq)后,重启容器。此时日志中出现事务回滚与清除记录(purg2_crash_cmt_trx),数据库成功启动。

3. 面试/技术核心总结

在此次排障中,涉及了以下几个关键的技术点,值得深入理解:

  1. Docker数据持久化与安全机制
    • 容器是短暂的,数据必须挂载。通过 docker inspect 确认挂载状态是排查数据是否安全的第标准动作。
    • 对于未挂载但需保留数据的容器,可通过 docker cp 将数据导出,再重新挂载运行。
  2. 容器内外文件权限映射
    • Docker使用Linux的UID/GID机制管理权限。当宿主机文件挂载入容器时,文件属主是UID而非用户名。
    • 遇到 code: 13, Permission denied 时,需检查宿主机文件权限是否对容器内运行服务的用户UID开放了读写权限。
  3. 数据库内存调优
    • 在容器化部署数据库时,极易出现OOM。需要了解数据库核心内存参数(如 BUFFER、MEMORY_POOL等),通过修改配置文件降低其内存申请上限,使其适配容器资源。
  4. Docker容器的前台运行机制
    • Docker容器需要前台进程维持运行。数据库容器的启动命令应指定自带的启动脚本(如 /opt/entrypoint.sh),该脚本不仅拉起数据库服务,还会通过 tail -f 等命令挂起进程,避免容器启动即退出。同时,配合 --shm-size 扩大共享内存,能有效防止服务异常。

如果你在面试中被问到“你在部署数据库时遇到过什么难题?”,你可以直接复述这个故事,重点强调:“我没有盲目删除容器,而是先排查了数据挂载情况,通过docker cp保全了数据;随后在解决权限和内存问题的过程中,深入到了容器权限映射和数据库底层参数调优”,这会极大体现你的工程严谨性和排障能力。

更多推荐