memlock 必须与 HugePages 对齐,因为 Oracle 实例启动时需锁定 SGA 到大页内存,若 soft/hard memlock 值小于 SGA_MAX_SIZE(字节),将触发 ORA-27123 错误;且 systemd 环境下 limits.conf 无效,须在 service 文件中显式配置 LimitMEMLOCK=。

limits.conf 中 memlock 设置为什么必须和 hugepages 对齐?
Oracle 推荐启用 hugepages,而 memlock 限制直接决定 Oracle 进程能否成功锁定 SGA 到大页内存。如果 oracle soft memlock 或 hard memlock 小于 SGA 总大小(尤其是启用了 AMM/ASMM 后的 target memory),实例启动时会报 ORA-27123: unable to attach to shared memory segment,且 ipcs -m 显示共享内存段未被锁定。
常见错误是照搬文档写死 134217728(128MB),但该值只适用于 SGA ≤128MB 的极小配置。实际应按物理内存和规划 SGA 计算:
-
memlockhard 值 ≥ SGA_MAX_SIZE(字节),建议再上浮 10% 预留内核页表开销 - 若使用 hugepages,需确保
vm.nr_hugepages已预分配足够页数(grep HugePages_ /proc/meminfo验证) - CentOS 7+ 上,
systemd会忽略limits.conf中的memlock,必须在/usr/lib/systemd/system/ohasd.service和oracle-rdbms.service中显式加LimitMEMLOCK=字段
nofile 和 nproc 值设太高反而导致 crs 启动失败?
很多人把 oracle hard nofile 65536 当成“越大越好”,却忽略了 RAC 环境下 root 用户启动的 CRS 进程(如 ohasd、crsd)并不继承 oracle 用户的 limits —— 它们由 systemd 或 init 启动,受 root 的资源限制约束。一旦 root hard nofile 仍为默认的 4096,crsd.bin 在打开大量 OCR/Voting Disk 句柄、ASM 磁盘路径、网络连接时就会静默失败,日志里只有 ERROR: Failed to start CRSD,根本不会提示句柄不足。
正确做法是:
- 同时设置
root soft nofile和hard nofile至少 65536(RHEL7/CentOS7 要求 ≥ 65536 才能通过 CRS 自检) -
nproc不宜盲目拉高:Oracle 11gR2 单实例线程数通常不超过 2000,设oracle hard nproc 16384足够;但root hard nproc若超过 8192,可能触发 systemd 的TasksMax限制(默认 512),需同步调大/etc/systemd/system.conf中的DefaultTasksMax - 验证是否生效:用
sudo -u oracle bash -c 'ulimit -n'和sudo -u root bash -c 'ulimit -n'分别检查
为什么改了 limits.conf 还是不生效?三个关键漏点
limits.conf 不是改完就生效的配置文件,它依赖 PAM 模块加载、会话类型、以及进程启动方式。最常踩的坑是:
- PAM 配置没覆盖所有登录路径:
/etc/pam.d/login只管 tty 登录;SSH 登录走/etc/pam.d/sshd,GUI 登录走/etc/pam.d/gdm或lightdm,必须全部补上session required pam_limits.so - 非登录 shell(如 cron、systemd service、su -c)默认不读
limits.conf:cron job 需在脚本开头加ulimit -n 65536;systemd 服务必须在 unit 文件中用LimitNOFILE=显式声明 - 用户组限制被忽略:若 oracle 用户属于
@dba组,但limits.conf写的是oracle用户行,组级规则(@dba soft nofile 65536)不会自动合并——PAM 是“先匹配用户名,再匹配组名”,且只取第一个匹配项,不会叠加
memlock 单位是 KB 还是 bytes?官方文档为何前后矛盾?
Oracle 官方文档(如 11gR2 Installation Guide)示例中写 oracle hard memlock 134217728,这个数字单位是 bytes,不是 KB。但很多 Linux 发行版(如 RHEL6)的 pam_limits.so 实现会把该值当作 KB 解析,导致实际锁定内存只有预期的 1/1024 —— 这就是为什么有些环境明明配了 128MB 却仍报 ORA-27123。
安全做法是统一用 bytes,并验证:
- 执行
ulimit -l查看当前生效值(单位 KB),再乘以 1024 对应到 bytes - 启动数据库后运行
cat /proc/$(pgrep ora_pmon)/limits | grep memlock,确认Max locked memory行的Max列数值与配置一致 - 若发现值异常小,检查是否被
/etc/security/limits.d/*.conf中其他文件覆盖(RHEL7+ 默认有20-nproc.conf限制普通用户进程数)
真正麻烦的从来不是参数怎么填,而是你永远不知道哪个进程在哪一层绕过了你设的限制。


















