在AIX平台上运维Oracle数据库时,内存管理是一个常见的挑战。与Linux不同,AIX的内存管理机制有其独特之处,传统的top、ps命令往往无法准确反映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。常用的性能工具如top、ps -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内存使用时,切记以下要点:
- 不要简单相信ps命令的输出——RSS包含共享内存,会严重高估实际使用量
- 使用svmon进行精确分析——它能区分私有内存和共享内存
- 正确计算私有内存——使用
RSS - TRS而非直接使用RSS - 注意文件系统缓存——它不属于Oracle控制,但会影响系统可用内存
- 设置合适的环境变量——
AIXTHREAD_SCOPE=S可显著减少内存消耗
理解这些概念后,你就能准确评估AIX平台上Oracle实例的真实内存需求,为容量规划和性能优化提供可靠依据。