一、问题描述
在虚拟机环境(4核16GB内存)上部署 truevoly/oracle-12c
容器镜像时,一切运行正常。然而,当在一台 128 核 CPU 和 512GB 内存的物理服务器上运行时,容器启动时出现了 ORA-00821
等错误,提示 SGA 的内存配置不足。
二、原因
通过在 GitHub 上查找相关资料,发现每个单独的线程大约会增加 22MB 的内存需求。因此,当核心数增多时,Oracle 数据库启动时会尝试为每个 CPU 核心分配内存,这就导致了内存需求大幅增加。
三、排查思路
刚开始可能走了点弯路,主要是在问AI,而忽略GitHub案例
1、启动镜像
docker run --restart always -d -p 8081:8080 -p 1522:1521 -v /usr/local/oracle/data_temp:/home/oracle/data_temp -v /etc/localtime:/etc/localtime:ro --name orac1 truevoly/oracle-12c
2、查看启动日志
docker logs -f 4eea316971a1706b1faf6dd469c276c334234f1f6f63824997aa71c00670abd5
正常情况下可以走到100%,访问数据库
Database not initialized. Initializing database.
Starting tnslsnr
Copying database files
1% complete
2% complete
4% complete
DBCA Operation failed.
Look at the log file "/u01/app/oracle/cfgtoollogs/dbca/xe/xe.log" for further details.
3、登录容器内部查看报错日志
docker exec -it orac1 bash
cat /u01/app/oracle/cfgtoollogs/dbca/xe/xe.log
Unique database identifier check passed.
/ has enough space. Required space is 6140 MB , available space is 2318404 MB.
File Validations Successful.
Copying database files
DBCA_PROGRESS : 1%
DBCA_PROGRESS : 2%
ORA-00821: Specified value of sga_target 1536M is too small, needs to be at least 1968M
ORA-01078: failure in processing system parameters
DBCA_PROGRESS : 4%
ORA-01034: ORACLE not available
ORA-01034: ORACLE not available
DBCA_PROGRESS : DBCA Operation failed.
我的第一反应是服务器资源充足,内存并不缺乏,因此怀疑是否是之前调整的内核参数,尤其是大页内存设置,导致了这个问题,把配置还原后不是这个原因。
报错解释
- ORA-00821: Specified value of sga_target 1536M is too small, needs to be at least 1968M
- 这个错误表示 Oracle 在初始化时尝试为
sga_target
设置 1536M 的内存大小,但实际上 Oracle 需要的最小值是 1968M。因此,sga_target
设置过小,导致初始化失败。- ORA-01078: failure in processing system parameters
- 这个错误通常是在处理系统参数(如
sga_target
)时失败,通常与内存设置有关,表明数据库无法使用当前配置启动。- ORA-01034: ORACLE not available
- 这个错误表明 Oracle 实例在尝试启动时没有成功运行。通常是由于数据库无法使用给定的内存配置而未能启动。
错误的根本原因是数据库初始化时内存分配不足,导致
sga_target
的值过小,无法满足 Oracle 数据库的需求。
3、限制容器的内存和 CPU 配置
github上面有说通过限制CPU来解决,这个思路有点启发
通过 docker run
命令,限制容器的内存和 CPU 使用,确保容器的资源分配符合 Oracle 数据库的要求,然后没有解决我的问题。
docker run --memory-swappiness=0 --memory="1g" --cpus="1.0" --rm=true --name=oracle1 -p 1521:1521 -e ORACLE_PASSWORD=123456 orac1 truevoly/oracle-12c
--memory="1g":限制容器使用的内存为 1GB。
--cpus="1.0":限制容器使用 1 个 CPU 核心。
--memory-swappiness=0:禁用容器的交换内存,避免性能下降。
对资源限制感兴趣的话可以去docker帮助文档
https://docs.docker.com/config/containers/resource_constraints/#configure-the-default-cfs-scheduler
4、容器内部修改内存配置
进入容器后,设置适当的 DBCA_TOTAL_MEMORY
来解决内存不足的问题,并重新执行初始化脚本:
想起来了之前做RAC的时候好像碰到过类似的问题
docker exec -it 4eea316971a1 bash
export DBCA_TOTAL_MEMORY=4096
执行脚本验证
root@4eea316971a1:/# bash entrypoint.sh
通过设置 DBCA_TOTAL_MEMORY 环境变量为 4096MB,能够帮助 Oracle 在容器中成功初始化。
已经生效了,看到了问题解决
四、优化Dockerfile
1、构建Dockerfile
将entrypoint.sh 拷贝到本地
修改脚本,重新build
2、重新运行观察
可以正常初始化
数据库链接正常
总结:
在虚拟机上运行时,由于核心数较少,内存需求较低,容器能够成功启动。但在物理机上,由于 128 核 CPU,内存需求显著增加,导致了内存分配不足,进而触发了错误。
这个镜像很好用的,我看网上分享oracle 12c快速启动大部分都在用这个镜像,估计很少在128C内存上运行吧。