结论是必须同时调整kernel.shmmax和kernel.shmall且按页面大小精确换算匹配,否则oracle可能报ora-27123或shmat时被oom killer终止;查当前值应以/proc/sys/kernel/shmmax和/proc/sys/kernel/shmall为准,而非文档或配置文件。

直接说结论:不是改一个参数就行,必须同时调 kernel.shmmax 和 kernel.shmall,且二者要按页面大小换算匹配——否则 shmget 可能成功,但 shmat 时被 OOM killer 杀掉,或者 Oracle 启动报 ORA-27123。
查当前值:别信文档,看 /proc 才算数
系统实际生效的值,只认 /proc/sys/kernel/shmmax 和 /proc/sys/kernel/shmall。运行以下命令确认:
cat /proc/sys/kernel/shmmax cat /proc/sys/kernel/shmall getconf PAGESIZE
注意三点:
-
shmmax单位是字节,比如33554432就是默认 32MB -
shmall单位是页(不是字节),常见 x86_64 是 4096 字节一页 - 必须用
getconf PAGESIZE确认页大小,不能硬猜——ARM 或某些容器环境可能用 64KB 大页
临时调大:验证用,不重启立刻生效
适合快速测试或调试,但重启后失效。推荐用 sysctl -w,它会做基础校验,比直接写 /proc 更安全:
sudo sysctl -w kernel.shmmax=2147483648 sudo sysctl -w kernel.shmall=524288
对应关系要手动算清:
- 设
shmmax=2GB(2147483648 字节)→ 页数 = ceil(2147483648 / 4096) = 524288 →shmall至少得设成这个数 - 如果只改
shmmax没同步改shmall,shmget成功,但首次shmat时内核发现总页数超限,直接触发 OOM - 写
/proc要 root 权限,且拼错路径(如/proc/sys/kernel/shm_max)会静默失败,无提示
永久生效:/etc/sysctl.conf + sysctl -p,缺一不可
编辑 /etc/sysctl.conf,追加两行(不要漏等号前后空格):
kernel.shmmax = 2147483648 kernel.shmall = 524288
然后必须执行:
sudo sysctl -p
常见错误:
- 只改了 conf 文件但没运行
sysctl -p,参数根本没加载 - 参数名写错,比如
shm_max或shmmx,sysctl -p不报错但也不生效 - 用
/etc/rc.local写 echo 命令——systemd 下基本不执行,已淘汰 - 设得过大:官方建议
shmmax不超过物理内存一半;shmall过大会让内核预留大量页表空间,反而挤占可用内存
为什么还是失败?别漏进程级限制
即使内核参数全调对,shmget 仍可能返回 ENOMEM,因为还有两层限制:
- 用户级:
ulimit -l限制“锁定内存”大小(单位 KB),共享内存段默认会被锁定。查当前值:ulimit -l;临时调高:ulimit -l 2097152(即 2GB) - 挂载点:
/dev/shm是 tmpfs,默认大小 64MB。POSIX 共享内存(shm_open)受此限制,需重新挂载:sudo mount -o remount,size=2G /dev/shm - 老内核隐式上限:比如 2.6.32 内核把
shmmax截断到 4GB,设更高也无效,只能cat /proc/sys/kernel/shmmax看最终值
真正卡住人的地方,往往不是不会改,而是改完没验证是否被内核真正接受,或者忽略了 shmall 必须按页面大小换算——shmmax 设对了,shmall 没算准,等于白调。











