当前位置:首页>Linux>全网最全 ORA-27102 + Linux Error 28 排查手册:别再盲目加内存条了!

全网最全 ORA-27102 + Linux Error 28 排查手册:别再盲目加内存条了!

  • 2026-09-07 15:43:42
全网最全 ORA-27102 + Linux Error 28 排查手册:别再盲目加内存条了!

注: 本文为安丫科技刘峰的原创,请尊重知识产权,转发请注明出处,不接受任何抄袭、演绎和未经注明出处的转载。

导

语

做数据库运维,最怕遇到这种“罗生门”式的故障:当你火急火燎地启动 Oracle 实例,屏幕上冷冰冰地甩给你一行 ORA-27102: out of memory,紧接着 Linux 内核补了一刀 Error 28: No space left on device。

你的第一反应肯定是:“完蛋,内存爆了?还是磁盘满了?”

可是当你颤抖着敲下 free -g 和 df -h,却发现物理内存还剩一大半,磁盘空间也空空荡荡。

那一刻,是不是有一种被系统“针对”的无力感?明明有资源,为什么数据库睁眼说瞎话?

别急,这根本不是物理内存不够,而是 Oracle 想要的那块“特殊地盘”被内核卡住了。

今天,我们就来扒一扒这个让无数 DBA 掉坑的经典故障,带你从原理到实战,彻底终结这个“假内存不足”的幽灵,让你在排障时不再迷茫。

01

问题现象与核心误区

当尝试启动一个配置有较大 SGA 的 Oracle 实例时,可能会遇到以下错误:

ORA-27102: out of memoryLinux-x86_64 Error: 28: No space left on device

核心误区

将此错误等同于物理内存(RAM)不足。

Error 28 (ENOSPC) 在此上下文中,并非指磁盘空间,而是指内核在为 Oracle 分配其所需的特定类型内存资源池时,该池“空间不足”。

这个资源池可能是 System V 共享内存、tmpfs 文件系统(/dev/shm),或最常见的 HugePages 内存池。

02

核心原理剖析:Oracle SGA 与 

 Linux 内存分配机制 

要理解该错误,必须先深入了解 Oracle SGA 的特性及其在 Linux 上的实现方式。

1

SGA 的本质:大块、连续、共享的内存区域

SGA(System Global Area)是 Oracle 实例的核心内存组件,用于缓存数据块、执行计划、SQL 解析结果等。

其关键特性是:

大(Large)

现代数据库的 SGA 通常以数十甚至数百 GB 计。

共享(Shared)

SGA 必须被实例的所有后台进程和服务器进程共享访问。

性能敏感(Performance-Sensitive)

对 SGA 的访问效率直接影响数据库的整体性能。

这些特性决定了 SGA 的分配不能像普通应用程序内存那样随意。

Oracle 必须向操作系统申请一块巨大的、连续的内存空间,并确保其高效、稳定。

2

Linux 为 Oracle 提供的三种内存分配模型 

根据 Oracle 的配置,它会选择以下三种模型之一来向 Linux 内核申请 SGA 内存。

模型一:System V Shared Memory (经典模型)

这是传统的 IPC(Inter-Process Communication)机制。

Oracle 请求内核创建一块或多块共享内存段,所有进程通过附加(attach)到这些段上来实现共享。

  • 工作原理

内核维护一个全局的共享内存段列表。

进程通过一个唯一的键(key)来创建或访问这些段。

  • 相关内核参数

    kernel.shmmax

    单个共享内存段的最大允许大小(Bytes)。如果 SGA 大于此值,Oracle 会尝试创建多个段。

    kernel.shmall

    系统范围内所有共享内存段的总大小上限,单位是内存页(通常为 4KB)。

    这是最关键的限制。

    如果所有 Oracle 实例的 SGA 总和,加上系统中其他使用 System V 共享内存的应用所需空间,超过了 shmall * PAGE_SIZE,新的分配请求就会失败,并可能返回 ENOSPC 错误。

模型二:AMM (Automatic Memory Management) via tmpfs

当启用 AMM(设置 MEMORY_TARGET 和 MEMORY_MAX_TARGET)时,Oracle 改变了内存管理策略。

它会在一个基于内存的文件系统 tmpfs 上创建一个或多个文件,然后通过内存映射(mmap)的方式将这些文件映射到自己的地址空间,作为 SGA 和 PGA 的统一管理区域。

  • 工作原理

    在 Linux 上,tmpfs 的默认挂载点是 /dev/shm。

    Oracle 在此目录下创建文件,文件的大小即为 SGA 和 PGA 的总和。

  • 限制因素

    此模型的瓶颈非常直接——/dev/shm 的挂载容量。

    如果 MEMORY_TARGET 的值大于 /dev/shm 的可用空间,Oracle 在创建映射文件时就会失败,返回 ENOSPC。

模型三:HugePages (现代推荐模型)

对于大 SGA 环境,使用标准的 4KB 内存页会导致极大的性能开销。

因为 CPU 需要维护一个庞大的页表(Page Table)来映射虚拟地址和物理地址,这会增加 TLB(Translation Lookaside Buffer)的缓存未命中率,即“TLB-thrashing”。

HugePages(在 Linux 中也称 HugeTLB)机制允许操作系统以更大的单位(通常是 2MB 或 1GB)来管理内存。

  • 工作原理

    a. 预分配

    系统管理员通过 vm.nr_hugepages 内核参数,在系统启动时预留一个固定大小的、连续的、不可交换的物理内存池。

    b. 独占式申请

    当 Oracle 配置为使用 HugePages(USE_LARGE_PAGES = TRUE 或 ONLY)时,它会向内核发出一个特殊的内存分配请求,明确要求从这个 HugePages 池中获取内存。

    c. “All-or-Nothing”原则

    这是导致 ORA-27102 的核心原则。

    如果 HugePages 池中的可用页数不足以满足整个 SGA 的需求,Oracle 不会降级去使用标准的 4KB 页,而是会直接放弃启动,报告内存分配失败。

03

故障诊断与实战分析:250GB 

 SGA 启动失败的根因定位

现在,我们运用上述原理,对 250GB SGA 启动失败的案例进行精确诊断。

1

 步骤一:确定内存管理模型

首先,检查 pfile 或 spfile,确认 MEMORY_TARGET 是否设置。

在本案例中,我们确认 MEMORY_TARGET 为 0,且 使用 HugePages。

2

步骤二:量化需求与供应

这是控制 I/O 争抢的核心机制。

autovacuum 的工作受到一套成本模型的限制:

步骤二:量化需求与供应

需求端(Oracle)

  • SGA 大小

    sga_target = 254464M ≈ 250 GiB

  • HugePage 大小

    通过 grep Hugepagesize /proc/meminfo 得到,通常为 2048 kB (2 MB)。

  • 所需 HugePages 数量 = SGA 总大小 / HugePage 大小 = (250 * 1024 * 1024) KB / 2048 KB = 128,000 页

供应端(Linux OS)

检查 /proc/meminfo 的 HugePages 相关信息:

HugePages_Total:   130000HugePages_Free:    120691HugePages_Rsvd:    93604
  • HugePages_Total

    系统总共配置了 130,000 个大页,理论上足够。

  • HugePages_Free

    但当前物理上空闲的只有 120,691 个。

  • HugePages_Rsvd

    更重要的是,有 93,604 个大页已被“预留”。

    Rsvd (Reserved) 指的是已被某个进程通过 mmap 请求,但尚未被内核实际分配物理页的“逻辑占位”。

    这些页面虽然计入 Free,但实际上已名花有主,不能被新进程使用。

供需对比分析:

  • 直接对比

    需求(128,000 页) > 物理空闲(120,691 页)。

    仅此一点,分配请求就已注定失败。

  • 考虑预留

    实际可供支配的页数远小于 120,691。

    一个保守的估算是 Free - Rsvd,即 120691 - 93604 = 27087 页。

    这个数字与 128,000 的需求相比,差距巨大。

结论

Oracle 实例向内核申请 128,000 个大页,内核发现 HugePages 池中可用的页数严重不足,因此拒绝了请求,返回 ENOSPC (Error 28)。

3

步骤三:检查权限与限制 

即使 HugePages 数量足够,如果 oracle 用户没有将大块内存锁定在物理内存中的权限,启动同样会失败。

检查命令

以 oracle 用户身份执行 ulimit -l。

要求

该值(单位 KB)必须大于等于 SGA 的大小。

若为 unlimited,则无此限制。

4

步骤四:排查资源占用与残留 

HugePages_Rsvd 过高或 HugePages_Free 过低,通常意味着资源已被占用。

正常占用

通过 ps -ef | grep pmon 检查,确认是否有其他 Oracle 实例(如 RAC 的另一个节点实例)正在运行。

异常残留

如果实例曾被异常终止(kill -9 或 shutdown abort),可能会留下“僵尸”共享内存段。

通过 ipcs -m 查看,若发现属于 oracle 用户的残留段,它们会持续占用系统 IPC 资源。

04

解决方案与修复策略

根据诊断出的具体根因,可采取以下相应的修复策略。

所有命令均应在具有相应权限的用户下执行(通常是 root 或 oracle)。

1

针对 HugePages 不足或被占用

这是最常见的场景。

解决方案的核心是“要么释放,要么增加”。

1)释放被占用的 HugePages(优先选项)

① 识别并正常关闭占用进程

首先,识别是哪个进程占用了 HugePages。

在 Oracle 环境中,通常是另一个数据库实例。

# 以 oracle 用户或 root 用户执行,查找正在运行的 Oracle 实例ps -ef | grep pmon# 示例输出,显示 eapdb1 实例正在运行# oracle   123451010:00 ?        00:00:01 ora_pmon_eapdb1

然后,正常关闭该实例以释放其占用的 HugePages。

# 以 oracle 用户执行# 设置正确的环境变量export ORACLE_SID=eapdb1# 连接并关闭实例sqlplus / as sysdbaSQL> shutdown immediate;

关闭后,再次检查 HugePages 是否已释放。

grep HugePages_Free /proc/meminfo

2

清理异常残留的 IPC 资源

如果实例曾被异常终止(如 kill -9),可能会留下“僵尸”共享内存段和信号量。

检查残留资源:

# 以 oracle 用户执行ipcs -m   # 检查共享内存ipcs -s   # 检查信号量

如果看到多个由 oracle 用户拥有,但其关联进程已不存在的条目,则为残留资源。

使用 startup force 自动清理(推荐)

 这是最安全的方法,Oracle 会自动清理与指定 SID 关联的残留 IPC 资源。

# 以 oracle 用户执行,确保 ORACLE_SID 指向崩溃的实例export ORACLE_SID=eapdb2sqlplus / as sysdbaSQL> startup force;

该命令会先执行 shutdown abort,清理资源,然后重新启动。

如果只想清理不想启动,可在启动后立即 shutdown immediate。

手动清理 IPC 资源(高风险,谨慎使用)

仅在 startup force 失效或需要编写自动化脚本时使用。

操作前必须确认没有相关的 Oracle 进程在运行。

# 以 root 或 oracle 用户执行# 自动清理所有属于 oracle 用户的共享内存段ipcs -m | grep oracle | awk '{print $2}' | xargs -n1 ipcrm shm# 自动清理所有属于 oracle 用户的信号量ipcs -s | grep oracle | awk '{print $2}' | xargs -n1 ipcrm sem

增加系统 HugePages 总量

如果释放资源后仍不够,或业务要求多实例同时运行,则需要增加 HugePages 的总供应量。

  • 临时增加(立即生效,重启后失效)

# 以 root 用户执行# 假设需要增加到 130000 个echo 130000 > /proc/sys/vm/nr_hugepages
  • 永久增加(推荐)

编辑 /etc/sysctl.conf 文件,修改或添加 vm.nr_hugepages 参数。

# 以 root 用户执行# 编辑文件vi /etc/sysctl.conf# 添加或修改行vm.nr_hugepages = 130000

保存后,执行以下命令使配置立即生效:

sysctl -p

2

针对 memlock 限制

如果 ulimit -l 显示的值小于 SGA 大小,需要调高该限制。

编辑 limits.conf 文件

# 以 root 用户执行vi /etc/security/limits.conf

为 oracle 用户添加或修改 memlock 配置

建议直接设置为 unlimited,以避免未来因 SGA 调整再次遇到此问题。

# 在文件末尾添加以下两行oracle   soft   memlock   unlimitedoracle   hard   memlock   unlimited

重新登录会话

limits.conf 的修改只对新的登录会话生效。

您必须退出当前的 oracle 用户会话,然后重新登录,新的 memlock 限制才会生效。

再次执行 ulimit -l 验证。

3

针对 ORA-00821 逻辑死循环

当调小 sga_target 后遇到此错误,说明 pfile 中明确设置的 SGA 组件之和大于新的 sga_target。

编辑 pfile 文件

# 以 oracle 用户执行vi /tmp/pfile_debug.ora

同时调小 sga_target 和相关组件

找到 sga_target、sga_max_size 以及所有明确设置的 db_cache_size, shared_pool_size, large_pool_size, java_pool_size 等参数。

修改策略(二选一)

  • 精确调整

    将这些组件参数的值按比例缩小,确保它们的总和小于新的 sga_target。

  • 自动管理(推荐用于临时启动)

    将 db_cache_size 等所有组件参数用 # 注释掉,只保留 sga_target 和 sga_max_size。这样 Oracle 会在新的 SGA 总预算内自动分配各组件大小。

示例(注释法):

# ...*.sga_max_size=50176M*.sga_target=50176M#*.db_cache_size=200000M   <-- 注释掉#*.shared_pool_size=40000M  <-- 注释掉# ...

使用修改后的 pfile 再次尝试启动

SQL> startup mount pfile='/tmp/pfile_debug.ora';

4

针对 AMM 模式下 /dev/shm 不足

如果数据库使用 AMM(MEMORY_TARGET > 0),且 /dev/shm 容量不足。

检查当前容量

df -h /dev/shm

临时扩容(立即生效,重启后失效)

# 以 root 用户执行# 假设需要扩容到 300GBmount -o remount,size=300G /dev/shm

永久扩容(推荐)

编辑 /etc/fstab 文件,修改 tmpfs 在 /dev/shm 上的挂载配置。

# 以 root 用户执行vi /etc/fstab# 找到 /dev/shm 对应的行,修改 size 参数# 如果没有,则添加一行tmpfs   /dev/shm   tmpfs   defaults,size=300G   00

为了使永久配置立即生效而无需重启,可以在修改 /etc/fstab 后,再执行一次临时的 remount 命令。

写在最后

看完这篇,下次再遇到 ORA-27102 和 Error 28 狼狈为奸时,千万别再憨憨地去打报告申请加内存条了。

技术人的价值,往往就体现在这种“透过现象看本质”的时刻。

报错信息只是表象,内核参数才是真相。不管是 SGA 配置过大,还是 HugePages 被僵尸进程占着茅坑不拉屎,只要你掌握了文中这套“查户口”式的诊断流程,就能像做外科手术一样精准切除病灶。

希望这篇干货能成为你手中的一把利剑,帮你解决深夜排障时的燃眉之急。

如果觉得文章对你有帮助,欢迎【点赞】、【在看】或【转发】给身边的运维兄弟。

关注【安呀智数据坊】,每天一点硬核干货,带你从“救火队员”进阶为“架构专家”。

作者介绍

大家好,我是刘峰,安丫科技创始人 & 数据库技术高级讲师,专注于 PostgreSQL、国产数据库运维与迁移、数据库性能优化 等方向。

作为 PG中国分会官方授权讲师、PostgreSQL ACE 讲师认证专家,我长期活跃在一线项目实战中,拥有 10年以上大型数据库管理与优化经验,曾深度参与电信、金融、政务等多个行业的数据库性能调优与迁移项目。

欢迎关注我,一起深入探索数据库的无限可能,技术交流不设限!

📌 觉得有收获的话,记得点赞、收藏、转发支持一下哦,别忘了关注我获取更多数据库干货~

安呀智数据坊|我们能做什么

无论你是业务系统的技术负责人,还是数据部门的第一响应人,我们都能为你提供可靠的支持:

  • 数据库类型支持

    Oracle / MySQL / PostgreSQL / SQL Server 等主流数据库

  • 核心服务内容

    性能优化 / 故障处理 / 数据迁移 / 备份恢复 / 版本升级 / 补丁管理

  • 系统性支持

    深度巡检 / 高可用架构设计 / 应用层兼容评估 / 运维工具集成

  • 专项能力补充

    定制课程培训 / 甲方团队辅导 / 复杂问题协作排查 / 紧急救援支持

📮 如果你有一张删不掉的表、一个跑不动的查询,或者一场说不清的升级风险,欢迎来找我们聊聊。

END

关键词回复(可见相应文章):

oracle、mysql、pg、postgresql、sql、性能优化、故障处理、数据迁移、备份恢复、版本升级、补丁管理、深度巡检、解决方案、架构设计......

添加微信好友1对1咨询

\ | /

★

动动你的手指

给【安呀智数据坊】加个星标吧~

这样你就不会丢下我啦~

记得加星标呀!

最新文章

随机文章