在AIX平台上运维Oracle数据库时,内存管理是一个常见的挑战。与Linux不同,AIX的内存管理机制有其独特之处,传统的topps命令往往无法准确反映Oracle的真实内存使用情况。本文将深入探讨如何在AIX平台上正确理解和监控Oracle实例的内存使用。

一、理解Oracle的三类进程

在深入内存分析之前,首先需要理解Oracle的三种进程类型:

1. 后台进程(Background Process)

当我们启动Oracle实例时,首先被召唤的是一组后台进程。这些进程与SGA共同构成了Oracle实例,包括:

  • LGWR:日志写入进程
  • DBWn:数据库写入进程
  • SMON:系统监控进程
  • PMON:进程监控进程
  • RECO:分布式恢复进程
  • CKPT:检查点进程
  • 11g之后还有更多...

在UNIX上,后台进程的命名格式为:ora_<功能名>_<SID>,例如ora_pmon_ORCL

2. 用户进程(User Process)

用户进程可能是sqlplus命令行、imp/exp工具,或用户开发的Java程序。当用户进程在本地启动时,它们不直接操作SGA或PGA,但仍需消耗一定数量的虚拟内存。

3. 服务进程/影子进程(Server Process / Shadow Process)

当启动一个sqlplus连接时(无论本地还是远程),都需要一个服务进程直接为该终端服务。在专用服务器模式下,影子进程与用户进程一一对应。进程命名格式为:oracle<SID>

二、Oracle内存使用的两大类型

Oracle的内存使用可划分为两大类型:

类型 说明 计算方式
私有内存(Private Memory) 仅供单个进程使用,主要是PGA 每个进程单独计算
共享内存(Shared Memory) 供多个进程共享,主要是SGA 只需累加一次

SGA被映射为虚拟地址,并被每个后台进程和前台进程attach。常用的性能工具如topps -lf无法区分私有内存和共享内存的使用情况。如果简单地将每个Oracle进程的内存使用量相加,会发现总量是SGA+PGA的几十倍——这显然是错误的。

要真正理解Oracle内存使用,必须能够分离私有内存和共享内存。在AIX平台上,svmon是完成这一任务的关键工具。

三、svmon工具详解

svmon是AIX平台上分析内存使用的核心工具,可通过安装perfagent.tools文件集获取。该命令只能由root用户执行。

安装svmon

# 检查是否已安装
lslpp -lI perfagent.tools

# 如未安装,使用smit安装
smit install_latest

svmon的主要报告类型

选项 报告类型 说明
-G 全局报告 显示整个系统的实际内存和分页空间使用统计
-P 进程报告 显示活动进程的内存使用统计
-S 段报告 显示指定数量段的内存使用情况
-D 详细段报告 显示指定段的详细信息
-U 用户报告 显示指定用户的内存使用统计
-C 命令报告 按命令名显示进程的内存使用统计

查看系统全局内存使用

# 每2秒刷新一次,共5次
svmon -G -i 2 5

               size      inuse       free        pin    virtual
memory        65527      64087       1440       5909      81136
pg space     131072      55824

               work       pers       clnt
pin            5918          0          0
in use        47554      13838       2695

输出字段说明:

  • size:内存总大小(4KB页)
  • inuse:正在使用的页数
  • free:空闲列表上的页数
  • pin:固定在RAM中的页数(不可被换出)
  • virtual:系统虚拟空间中分配的页数
  • work:工作页数
  • pers:持久页数(文件系统缓存)
  • clnt:客户端页数(远程文件页)

查看Oracle进程的内存使用

# 查看单个进程的详细内存使用
svmon -P <pid>

# 示例:查看PMON进程
svmon -P 782530

Pid Command          Inuse   Pin  Pgsp Virtual
782530 ora_pmon_shbas 29598  1451   182   16560

Vsid    Esid Type Description              Inuse  Pin Pgsp Virtual
1781       3 work shmat/mmap              11824    0    0   11824    # SGA
1761       1 pers code,large file /dev     9681    0    -       -    # Oracle二进制
0          0 work kernel seg               3982 1450  182    3390    # 内核段
18018      d work shared library text      2852    0    0     158    # 共享库
4764       2 work process private          1127    1    0    1127    # 私有内存(PGA)
f74f       f work shared library data        81    0    0      61    # 共享库数据

关键段类型解读:

  • shmat/mmap:SGA共享内存段,所有Oracle进程共享
  • code / pers:Oracle二进制代码段(TRS),所有进程共享
  • process private:进程私有内存(PGA),每个进程独占
  • shared library:共享库,所有进程共享

查看用户总内存使用

# 查看oracle用户的总内存使用
svmon -U oracle | head -40

User              Inuse      Pin     Pgsp  Virtual
oracle          1084391    82284   209510  1131219

EXCLUSIVE segments                  Inuse      Pin     Pgsp  Virtual
                                  1000521    13833   207071  1045120

四、使用ps命令分析Oracle内存

虽然svmon是最准确的工具,但ps v命令也能提供有价值的信息。

ps -lf vs ps v 对比

# ps -lf 显示的SZ值是误导性的
$ ps -lfp 5029994
F S   UID      PID   PPID  C PRI NI ADDR     SZ    WCHAN  STIME  TTY  TIME CMD
240001 A orauser 5029994    1  0  60 20 1d2e7b510 98000        Apr 15   - 190:34 ora_pmon_DEC

# ps v 显示了更有意义的RSS和TRS
$ ps v 5029994
PID    TTY STAT  TIME PGIN  SIZE   RSS   LIM  TSIZ   TRS %CPU %MEM COMMAND
5029994  - A  190:34    4  9152 144536    xx 88849 135384  0.0  0.0 ora_pm

关键字段说明

字段 说明 计算公式
RSS 驻留集大小(KB) = (工作段页数 + 代码段页数) × 4
TRS 文本驻留集大小(KB) = 代码段页数 × 4
SIZE 数据段虚拟大小(KB) = (私有段 + 库数据段) Pgspace × 4

计算进程私有内存的正确方法:

私有内存 = RSS - TRS

以上例为例:
144536(RSS) - 135384(TRS) = 9152 KB
9152 × 1024 = 9,371,648 bytes ≈ 9MB

而非 ps -lf 显示的 98000 KB (约95MB)!

TRS与Oracle二进制文件的关系

TRS(代码段)的大小与$ORACLE_HOME/bin/oracle二进制文件大小基本一致:

# 查看代码段
svmon -P 782530 | grep "clnt text data BSS heap"
3608dc 10 clnt text data BSS heap, s 32546 0 - -

# 32546页 × 4KB = 130,184KB

# Oracle二进制文件大小
ls -l `which oracle`
-rwsr-s--x 1 oracle dba 133931095 Apr 02 2009 /ora10g/.../bin/oracle
# 133,931,095 bytes ≈ 130,792KB

五、估算Oracle总内存使用

方法一:使用ps命令估算

# 估算所有Oracle进程的私有内存总量
ps vg | grep ora | awk '{sum=sum+$7-$10} END {print sum/1024}'
2432.89  # 单位:MB

# 查看SGA大小
sysresv
# 或
ipcs -mb | grep <shmid>

Oracle总内存估算公式:

总内存 = Σ(每个进程的RSS-TRS) + TRS + SGA

示例:
私有内存总量:2432 MB
TRS(代码段):47 MB
SGA:1536 MB
总计:2432 + 47 + 1536 = 4015 MB

方法二:使用svmon验证

svmon -U oracle | head -40

# EXCLUSIVE segments 显示oracle用户独占的内存
EXCLUSIVE segments                  Inuse      Pin     Pgsp  Virtual
                                  1000521    13833   207071  1045120

# PageSize详情
PageSize     Inuse      Pin     Pgsp  Virtual
s 4 KB      977721      153   207071  1022320
m 64 KB       1425      855        0     1425

# 计算:977721×4KB + 1425×64KB = 4015MB ✓

六、AIX文件系统缓存的影响

重要提示:svmon会将文件系统缓存计入曾经申请过这些文件页的进程。但这些缓存是由AIX操作系统控制的,与Oracle的PGA/SGA无关。

如果使用裸设备(Raw Device),就不存在大量文件系统缓存的问题。但对于使用文件系统的环境,可以通过vmo工具(AIX 5.3+,原vmtune)调节相关参数:

# 查看当前VMM参数
vmo -a

# 关键参数
minperm    # 文件缓存最小百分比
maxperm    # 文件缓存最大百分比
strict_maxperm  # 是否强制maxperm限制

# 调整示例(限制文件缓存最大50%)
vmo -p -o maxperm%=50
vmo -p -o strict_maxperm=1

七、AIX环境变量优化

在AIX上运行Oracle,建议设置以下环境变量以减少每个进程的内存消耗:

# 在Oracle环境脚本中添加(如 .profile)

# 使用系统线程作用域(强烈推荐)
export AIXTHREAD_SCOPE=S

# AIX 4.3 和 5.1 还需设置
export NUM_SPAREVP=1

这些设置可以显著减少每个Oracle进程的内存分配,特别是在AIX 5.2及更高版本上。

八、常见问题与MOS参考

问题:每个连接消耗约100MB内存?

这是AIX平台上的一个常见误解。ps命令显示的RSS值包含了共享内存(SGA),不能直接用于判断进程的私有内存消耗。正确的计算方法是RSS - TRS

相关MOS文档

  • Note 123754.1:AIX: Determining Oracle memory usage on AIX
  • Note 259983.1:Memory Consumption on AIX
  • Note 259779.1:Using system thread scope for Oracle on AIX
  • Bug 3662963:Memory required for shadow process using dblink increased
  • Bug 5076085:Private memory increase after applying 9207

九、内存分析实战示例

完整的内存分析流程

# 1. 查看系统全局内存状态
svmon -G

# 2. 找出内存使用最多的进程
svmon -Pau 10

# 3. 分析特定Oracle进程
svmon -P <pid>

# 4. 查看oracle用户的总内存使用
svmon -U oracle

# 5. 快速估算所有Oracle进程的私有内存
ps vg | grep ora | awk '{sum=sum+$7-$10} END {print sum/1024 " MB"}'

# 6. 查看SGA大小
ipcs -mb | grep -i oracle

svmon输出与ps v的对应关系

ps v 字段         svmon 对应
─────────────────────────────────────────────────
SIZE    =  4 × (process private Pgsp + lib data Pgsp)
RSS     =  4 × (process private Inuse + code Inuse + lib data Inuse)
TRS     =  4 × (code Inuse)

写在最后

在AIX平台上分析Oracle内存使用时,切记以下要点:

  1. 不要简单相信ps命令的输出——RSS包含共享内存,会严重高估实际使用量
  2. 使用svmon进行精确分析——它能区分私有内存和共享内存
  3. 正确计算私有内存——使用RSS - TRS而非直接使用RSS
  4. 注意文件系统缓存——它不属于Oracle控制,但会影响系统可用内存
  5. 设置合适的环境变量——AIXTHREAD_SCOPE=S可显著减少内存消耗

理解这些概念后,你就能准确评估AIX平台上Oracle实例的真实内存需求,为容量规划和性能优化提供可靠依据。