Oracle 内存结构 SGA / PGA / UGA 详解
Oracle 内存结构 SGA / PGA / UGA 详解
适用版本:Oracle Database 19c / 23ai 阅读基础:了解 Oracle 实例(Instance)的基本概念 文档版本:v1.0 / 2026-07
目录
- 1. 概述:为什么内存结构是 Oracle 性能的核心
- 2. Oracle 内存结构总览
- 3. SGA(System Global Area)系统全局区
- 4. PGA(Program Global Area)程序全局区
- 5. UGA(User Global Area)用户全局区
- 6. 内存管理方式对比
- 7. 内存监控与诊断视图
- 8. 常见坑与最佳实践
- 9. 常见问题 FAQ
- 10. 参考资料
1. 概述:为什么内存结构是 Oracle 性能的核心
Oracle 数据库的性能瓶颈 80% 以上与内存配置相关。原因在于:
- 磁盘 I/O 与内存访问速度差距巨大:磁盘毫秒级(ms),内存纳秒级(ns),相差 6 个数量级
- Oracle 是基于缓存(Cache)的数据库:所有数据访问都先经过 SGA 的 Buffer Cache
- 解析成本高:SQL 硬解析需要消耗大量 CPU 和共享池内存
- 排序/哈希需要内存:PGA 不足会触发临时表空间读写,性能下降 10-100 倍
理解 SGA / PGA / UGA 三个内存区域,是 Oracle 调优和排错的基础。本文基于 Oracle 官方文档 Concepts 第 15 章[1] 与 23ai 新增的 Managed Global Area(MGA)[2],结合社区实战经验,系统讲解。
2. Oracle 内存结构总览
Oracle 实例启动时分配的内存区域分为四大类(23ai 新增 MGA)[1][2]:
┌─────────────────────────────────────────────────────────────┐
│ Oracle Instance Memory │
├─────────────────────────────────────────────────────────────┤
│ SGA (System Global Area) ── 共享,所有 server/bg │
│ ├─ Database Buffer Cache 进程共享
│ ├─ Shared Pool (Library Cache + Data Dict Cache + Result Cache)
│ ├─ Redo Log Buffer │
│ ├─ Large Pool │
│ ├─ Java Pool │
│ ├─ Streams Pool │
│ └─ Fixed SGA │
├─────────────────────────────────────────────────────────────┤
│ PGA (Program Global Area) ── 私有,每个进程独有 │
│ ├─ Private SQL Area (Session-specific) │
│ ├─ SQL Work Area (Sort/Hash/Bitmap) │
│ └─ Stack / Control variables │
├─────────────────────────────────────────────────────────────┤
│ UGA (User Global Area) ── 会话级,位置随连接模式变 │
│ └─ Session State(含 PL/SQL 变量、Cursor 状态等) │
├─────────────────────────────────────────────────────────────┤
│ MGA (Managed Global Area, 23ai) ── 半共享,跨可信进程 │
└─────────────────────────────────────────────────────────────┘
关键关系:
- PGA 包含 UGA:在专用服务器(Dedicated Server)模式下,UGA 是 PGA 的一部分
- SGA 包含 UGA:在共享服务器(Shared Server)模式下,UGA 位于 SGA 的 Large Pool(若未配置 Large Pool 则在 Shared Pool)
- PGA 永远不在 SGA 中:PGA 是进程私有的,绝不会被分配到 SGA 共享内存段中[1]
3. SGA(System Global Area)系统全局区
3.1 SGA 概念与共享特性
SGA 是一组共享内存结构的集合,包含一个 Oracle 数据库实例的数据和控制信息。所有 server 进程和 background 进程都共享 SGA[1]。
特性:
- 读写共享:所有进程可读,多个进程可并发写不同区域
- 生命周期:实例启动时分配(
startup nomount),实例关闭时释放 - 共享内存机制:底层通过操作系统 Shared Memory(如 Linux 的
shmget)实现 - 粒度分配:SGA 以 granule(粒度)为单位动态扩展,128 MB SGA 以下粒度为 4 MB,以上为 16 MB
查看 SGA:
-- 方式一:sqlplus 命令
SQL> SHOW SGA
Total System Global Area 3290345472 bytes
Fixed Size 2217832 bytes
Variable Size 1795164312 bytes
Database Buffers 1476395008 bytes
Redo Buffers 16568320 bytes
-- 方式二:查询视图
SELECT name, bytes/1024/1024 AS "Size(MB)" FROM v$sga;
SELECT * FROM v$sgainfo;
SGA 各组件大小(典型 OLTP 系统):
| 组件 | 占 SGA 比例 | 典型大小(16 GB SGA) | 增长性 |
|---|---|---|---|
| Buffer Cache | 60-70% | 10 GB | 自动 |
| Shared Pool | 15-25% | 3 GB | 自动 |
| Redo Log Buffer | <1% | 128 MB | 静态 |
| Large Pool | 5-10% | 1 GB | 自动 |
| Java Pool | 1-5% | 256 MB | 自动 |
| Streams Pool | 1-5% | 256 MB | 自动 |
| Fixed SGA | <1% | 2 MB | 静态 |
3.2 Database Buffer Cache 数据库高速缓冲区
作用:缓存从数据文件读取的数据块副本,所有用户进程共享。命中则直接读内存,未命中则触发磁盘 I/O[1][3]。
Buffer 的 4 种状态[1]:
| 状态 | 含义 |
|---|---|
| Pinned | 正在被某个进程访问,其他进程需等待 |
| Clean | 内容与磁盘一致,可被立即重用 |
| Free / Unused | 从未使用过(实例刚启动) |
| Dirty | 内容被修改过,与磁盘不一致,需 DBWn 写盘后才能重用 |
管理机制:两个链表[1][3]:
- LRU List(最近最少使用链表):维护所有 buffer 的访问顺序。包含 free、pinned、未加入 dirty list 的脏块
- Write List / Dirty List(写链表/脏链表):保存所有 dirty buffer,等待 DBWn 写入磁盘
LRU 算法工作流程[3]:
- 用户进程请求数据 → 先在 Buffer Cache 查找(Cache Hit)
- 未命中(Cache Miss)→ 需要从磁盘读入 → 在 LRU 链表尾部找 free buffer
- 搜索途中遇到 dirty buffer → 移到 Dirty List,继续搜索
- 找到 free buffer → 从磁盘读入数据 → 移到 LRU 的 MRU 端
- 搜索超过阈值仍未找到 → 触发 DBWn 写脏块
全表扫描的特殊处理[1]:
全表扫描读入的数据块会被放到 LRU 链表尾部(而非 MRU 端),这样大表扫描不会冲掉热点数据。可通过 CACHE hint 改变此行为。
Multiple Buffer Pool[3]:
-- 配置三种 buffer pool
ALTER SYSTEM SET db_cache_size = 8G;
ALTER SYSTEM SET db_keep_cache_size = 2G; -- KEEP 池
ALTER SYSTEM SET db_recycle_cache_size = 1G; -- RECYCLE 池
-- 将对象指定到对应池
ALTER TABLE hot_table STORAGE (BUFFER_POOL KEEP);
ALTER TABLE archive_table STORAGE (BUFFER_POOL RECYCLE);
| 池 | 用途 | LRU 策略 |
|---|---|---|
| Default | 默认池 | 标准 LRU |
| Keep | 经常访问的小表/索引 | 尽量不淘汰 |
| Recycle | 很少重用的数据(如大表扫描结果) | 快速淘汰 |
非默认块大小 Buffer:
-- 配置 2K/4K/16K/32K 缓冲池(用于传输表空间)
ALTER SYSTEM SET db_16k_cache_size = 1G;
坑 1:db_2k_cache_size 等不能用于标准块大小(如标准块是 8K,则 db_8k_cache_size 不存在,由 db_cache_size 配置)。
3.3 Shared Pool 共享池
作用:缓存可被多个会话共享的各种结构,是 SGA 中最复杂的组件[1][3]。
核心子组件:
3.3.1 Library Cache 库缓存
存储已解析和执行的 SQL、PL/SQL 代码、Java 类等。包含:
- Shared SQL Area:每条 SQL 语句的解析树、执行计划、统计信息
- Shared PL/SQL Area:存储过程、函数、包、触发器的解析代码
- Control structures:锁、library cache handle 等
SQL 共享的条件(必须字符级完全一致):
- 文本字符完全相同(包括大小写、空格、换行)
- 引用的对象 schema 相同
- 绑定变量类型与长度相近
- 优化器模式相同
- NLS 环境一致
坑 2:以下两条 SQL 在 Library Cache 中是不同的 cursor:
SELECT * FROM emp WHERE empno = 7900;
SELECT * FROM emp WHERE empno = 7900; -- 末尾多一个空格
这就是为什么生产环境必须用绑定变量:
-- ✅ 推荐:使用绑定变量,可被多个会话共享
SELECT * FROM emp WHERE empno = :1;
-- ❌ 避免:字面值 SQL,每次值不同都触发硬解析
SELECT * FROM emp WHERE empno = 7900;
SELECT * FROM emp WHERE empno = 7901;
3.3.2 Data Dictionary Cache 数据字典缓存
又称 Row Cache,缓存数据字典表的内容(如 SYS.OBJ$、SYS.USER$、SYS.TS$ 等)。
作用:解析 SQL 时无需反复读 SYSTEM 表空间的数据文件。
3.3.3 Result Cache 结果缓存
缓存查询结果,下次相同查询直接返回缓存结果(11g 引入)。
-- 启用结果缓存
ALTER SYSTEM SET result_cache_mode = FORCE;
ALTER SYSTEM SET result_cache_max_size = 1G;
-- 在查询中使用 hint
SELECT /*+ result_cache */ * FROM products WHERE category = 'PHONES';
适用场景:查询结果稳定不变(如静态字典表)、查询本身计算量大。
坑 3:Result Cache 对频繁更新的表是性能杀手,因为每次 DML 都会使其失效并重新构建。
3.4 Redo Log Buffer 重做日志缓冲区
作用:缓存 redo entries(重做条目),暂存于内存中,由 LGWR 异步写入在线 redo log 文件[1]。
特性:
- 大小由
LOG_BUFFER参数控制,默认 14 MB,不能动态调整 - 循环使用(circular buffer)
- 任何 DML/DDL 操作都会产生 redo entry
LGWR 写入触发条件[1]:
- 用户提交(COMMIT)
- Redo Log Buffer 三分之一满(1/3 full)
- Redo Log Buffer 中未写入数据达到 1 MB
- 每 3 秒一次(DBWR 写之前)
- 切换日志文件(log switch)
坑 4:LOG_BUFFER 太小会导致频繁的 LGWR 写入,引发 log file sync 等待事件。生产环境建议 ≥ 64 MB。
3.5 Large Pool 大池
作用:可选的 SGA 区域,用于缓冲大块 I/O 请求,避免 Shared Pool 内存碎片[1]。
使用场景:
- RMAN 备份恢复时的 I/O buffer
- 共享服务器(Shared Server)模式下的 UGA
- 并行查询(Parallel Query)的消息缓冲区
- Oracle Streams / GoldenGate
配置:
ALTER SYSTEM SET large_pool_size = 1G;
坑 5:启用共享服务器模式但未配置 Large Pool 时,UGA 会从 Shared Pool 分配,导致 Shared Pool 严重碎片化、library cache latch 争用。
3.6 Java Pool Java 池
作用:在数据库中运行 Java 存储过程(CREATE JAVA)时的 JVM 内存[1]。
ALTER SYSTEM SET java_pool_size = 256M;
未使用 Java 存储过程的数据库可设为 0。
3.7 Streams Pool 流池
作用:Oracle Streams、LogMiner、GoldenGate 使用的内存区域[1]。
ALTER SYSTEM SET streams_pool_size = 512M;
启用 GoldenGate 或 Streams 时必须配置。
3.8 Fixed SGA 固定区
作用:包含 Oracle 内部的指针、状态变量、数据结构等管理信息,与具体数据库无关[1]。
大小固定(几 MB),不可配置,由 Oracle 自动分配。
3.9 Result Cache 结果缓存
(见 3.3.3,独立组件视角)
4. PGA(Program Global Area)程序全局区
4.1 PGA 概念与私有特性
PGA 是 Oracle 进程私有的内存区域,包含该进程专属的数据和控制信息。PGA 不在 SGA 中分配,永远不会被其他进程共享[1]。
特性:
- 每个服务器进程(Server Process)和后台进程(Background Process)都有自己的 PGA
- 进程启动时分配,结束时释放
- 实例 PGA = 所有进程 PGA 的总和
- 由
PGA_AGGREGATE_TARGET控制总大小(自动管理模式)
查看 PGA:
SELECT name, value/1024/1024 AS "MB" FROM v$pgastat;
4.2 PGA 内部结构
┌──────────────────────────────────────┐
│ PGA (per process) │
├──────────────────────────────────────┤
│ 1. Stack Area │ -- 进程栈,保存本地变量
│ 2. Session Memory (if dedicated) │ -- 专用服务器下 = UGA
│ 3. Private SQL Area │
│ ├─ Persistent Area │ -- 绑定变量信息,cursor 关闭时释放
│ └─ Runtime Area │ -- 执行时使用
│ 4. SQL Work Area │
│ ├─ Sort Area │ -- 排序
│ ├─ Hash Area │ -- 哈希连接
│ └─ Bitmap Merge Area │ -- 位图索引合并
└──────────────────────────────────────┘
4.3 Private SQL Area 私有 SQL 区
存储每个会话独有的 SQL 执行状态,与 Shared Pool 中的 Shared SQL Area(共享部分)对应[1]。
| 子区域 | 内容 | 生命周期 |
|---|---|---|
| Persistent Area | 绑定变量值、安全上下文 | Cursor 关闭时释放 |
| Runtime Area | 执行时状态(当前行、排序进度等) | 执行第一步时分配,执行结束释放 |
专用 vs 共享服务器下 Private SQL Area 位置[1]:
- 专用服务器:Private SQL Area 在 PGA 中
- 共享服务器:Persistent Area 在 SGA 的 Large Pool 中(因为会话可能切换服务器进程),Runtime Area 仍在 PGA 中
4.4 SQL Work Area SQL 工作区
PGA 中最重要的性能相关区域,决定排序/哈希/位图操作是否在内存完成[1]。
| 工作区 | 用于 | 不足时降级 |
|---|---|---|
| Sort Area | ORDER BY、GROUP BY、DISTINCT、UNION、索引创建 | 写入 TEMP 表空间 |
| Hash Area | Hash Join、Hash Group By | 写入 TEMP 表空间 |
| Bitmap Merge Area | 位图索引合并 | 性能显著下降 |
| Bitmap Create Area | 位图索引创建 | 性能下降 |
性能影响:
- 内存中完成(in-memory):纳秒级
- 单次写盘(1-pass):毫秒级,慢 1000 倍
- 多次写盘(multi-pass):性能灾难
4.5 PGA 自动管理
由 WORKAREA_SIZE_POLICY = AUTO + PGA_AGGREGATE_TARGET 启用[4]。
-- 启用自动 PGA 管理
ALTER SYSTEM SET workarea_size_policy = AUTO;
ALTER SYSTEM SET pga_aggregate_target = 4G;
-- 单个 SQL 工作区上限
-- 由 _pga_max_size 决定(默认 200 MB,可调)
-- 超过部分会自动写入 TEMP
经验配比[4]:
| 系统类型 | PGA 占总内存 | 说明 |
|---|---|---|
| OLTP | 20% | 排序/哈希少 |
| DSS / 数据仓库 | 50% | 大量排序、Hash Join |
| 混合 | 30% | 折中 |
查看 PGA 顾问建议:
SELECT pga_target_for_estimate / 1024 / 1024 AS "PGA Target(MB)",
estd_pga_cache_hit_percentage AS "Cache Hit(%)",
estd_overalloc_count AS "Overalloc"
FROM v$pga_target_advice;
5. UGA(User Global Area)用户全局区
5.1 UGA 与连接模式的关系
UGA 是会话级内存,存储会话状态(session state),其位置取决于连接模式[1]:
| 连接模式 | UGA 位置 | 原因 |
|---|---|---|
| 专用服务器(Dedicated Server) | PGA 中 | 一个会话绑定一个进程,进程私有内存即可 |
| 共享服务器(Shared Server) | SGA 的 Large Pool 中(未配置时在 Shared Pool) | 会话在不同服务器进程间切换,必须共享 |
| DRCP(Database Resident Connection Pooling) | SGA 中 | 类似共享服务器 |
5.2 UGA 内容
UGA 包含会话相关的所有状态[1]:
- 会话变量:PL/SQL 包变量、会话级变量
- 登录信息:用户身份、权限、角色
- Cursor 状态:打开的 cursor、当前 fetch 位置
- Sort Area 的 Retained 部分:
SORT_AREA_RETAINED_SIZE,cursor 关闭前仍保留 - OLAP 页缓存(如启用)
查看 UGA:
SELECT name, value FROM v$statname n, v$sesstat s
WHERE n.statistic# = s.statistic#
AND n.name LIKE '%uga%'
AND s.sid = USERENV('SID');
6. 内存管理方式对比
6.1 手动内存管理
逐个设置每个组件大小:
ALTER SYSTEM SET db_cache_size = 8G;
ALTER SYSTEM SET shared_pool_size = 3G;
ALTER SYSTEM SET pga_aggregate_target = 4G;
ALTER SYSTEM SET large_pool_size = 1G;
ALTER SYSTEM SET java_pool_size = 256M;
-- ...
适用场景:老版本兼容(9i 之前)、特殊调优、问题排查。
缺点:组件间不能动态调配,配置繁琐。
6.2 ASMM 自动共享内存管理
只需设置 SGA_TARGET,SGA 内部各组件自动调整(PGA 需单独配置)[1]。
ALTER SYSTEM SET sga_target = 16G SCOPE=BOTH;
ALTER SYSTEM SET pga_aggregate_target = 4G SCOPE=BOTH;
-- 仍可设置下限保护
ALTER SYSTEM SET db_cache_size = 4G; -- 至少 4G
ALTER SYSTEM SET shared_pool_size = 2G; -- 至少 2G
特点:
- 只能动态减少未使用的内存,不能从有数据的区域抢
- 与 HugePages 兼容(推荐)
- 19c 默认模式
6.3 AMM 自动内存管理
只需设置 MEMORY_TARGET,SGA 与 PGA 之间自动调配[1]:
ALTER SYSTEM SET memory_target = 20G;
ALTER SYSTEM SET memory_max_target = 24G;
坑 6:AMM 与 HugePages 不兼容[1]
AMM 使用 MEMORY_TARGET 创建的共享内存段在动态调整时,会破坏 HugePages 的连续性。生产环境强制要求 HugePages,因此生产环境禁用 AMM,使用 ASMM。
6.4 Unified Memory 统一内存管理(23ai)
23ai 引入新参数 MEMORY_SIZE,统一管理 SGA / PGA / MGA / UGA[2]:
ALTER SYSTEM SET memory_size = 20G;
MGA(Managed Global Area)[2]:23ai 新增的半共享内存区域,可被一组受信任的 Oracle 进程动态共享,比 SGA 更灵活。
6.5 三种管理方式选择决策
是否生产环境?
├─ 是 → 启用 HugePages → ASMM(推荐)
└─ 否(开发/测试)
├─ 内存 < 8 GB → AMM
└─ 内存 ≥ 8 GB → ASMM
| 场景 | 推荐模式 | 关键参数 |
|---|---|---|
| 生产 OLTP | ASMM | SGA_TARGET + PGA_AGGREGATE_TARGET + HugePages |
| 生产 DSS | ASMM | 同上,PGA 占比更高 |
| 开发测试 | AMM | MEMORY_TARGET |
| 老系统升级 | 手动 | 保持原配置 |
| 23ai 新建库 | Unified Memory | MEMORY_SIZE |
7. 内存监控与诊断视图
7.1 SGA 相关视图
-- SGA 总览
SELECT * FROM v$sga;
SELECT * FROM v$sgainfo;
-- SGA 动态组件
SELECT component, current_size/1024/1024 AS "MB"
FROM v$sga_dynamic_components;
-- SGA 顾问建议
SELECT sga_size, sga_size_factor, estd_db_time_factor
FROM v$sga_target_advice;
-- SGA resize 操作历史
SELECT * FROM v$sga_resize_ops;
7.2 PGA 相关视图
-- PGA 总览
SELECT name, value/1024/1024 AS "MB" FROM v$pgastat;
-- PGA 进程级详情
SELECT spid, program, pga_used_mem, pga_alloc_mem, pga_max_mem
FROM v$process
ORDER BY pga_alloc_mem DESC;
-- PGA 顾问建议
SELECT pga_target_for_estimate/1024/1024 AS "MB",
estd_pga_cache_hit_percentage
FROM v$pga_target_advice;
-- 工作区使用
SELECT sql_id, operation_type, policy, last_memory_used/1024/1024 AS "MB",
last_execution
FROM v$sql_workarea
ORDER BY last_memory_used DESC;
7.3 UGA / Session 相关视图
-- 每个会话的内存
SELECT se.sid, se.username,
s.value/1024/1024 AS "UGA(MB)",
p.value/1024/1024 AS "PGA(MB)"
FROM v$session se, v$sesstat s, v$statname sn, v$sesstat p, v$statname pn
WHERE se.sid = s.sid
AND s.statistic# = sn.statistic#
AND sn.name = 'session uga memory'
AND se.sid = p.sid
AND p.statistic# = pn.statistic#
AND pn.name = 'session pga memory'
ORDER BY s.value DESC;
-- 系统级内存总览
SELECT * FROM v$memory_dynamic_components;
7.4 关键等待事件
| 等待事件 | 含义 | 调优方向 |
|---|---|---|
free buffer waits | 找不到 free buffer | 增大 Buffer Cache、检查 DBWn |
buffer busy waits | buffer 被占用 | 减少热点块、调整 PCTFREE |
latch: shared pool | Shared Pool 闩锁争用 | 使用绑定变量、增大 Shared Pool |
latch: cache buffers chains | Buffer Cache 闩锁争用 | 减少热点块、增加 DBWn |
library cache lock | Library Cache 锁 | 检查 DDL 与硬解析 |
log file sync | 提交时等 LGWR | 增大 Redo Log Buffer、检查磁盘 I/O |
direct path read temp | 排序/哈希写盘 | 增大 PGA |
8. 常见坑与最佳实践
坑 1:HugePages 未启用导致 Page Walk 开销
现象:SGA 较大(> 8 GB)时实例启动慢,alert log 警告。
原因:默认 4 KB 页面管理大内存会产生大量页表项,CPU 浪费在 page table walk。
解决:
# 1. 计算所需大页数(每页 2 MB)
# 所需大页数 = SGA_SIZE_MB / 2
# 例如 SGA 16 GB → 8192 / 2 = 4096 大页
# 2. 配置 sysctl
echo "vm.nr_hugepages = 4096" >> /etc/sysctl.conf
sysctl -p
****** 3. 关闭 AMM(与 HugePages 不兼容)
ALTER SYSTEM SET memory_target = 0;
# 4. 重启系统
reboot
# 5. 验证
grep Huge /proc/meminfo
坑 2:未用绑定变量导致 Shared Pool 撑爆
现象:v$librarycache 中 SQL AREA 的 gethitratio < 90%,shared pool latch 争用严重。
解决:
-- 1. 设置 cursor_sharing(临时方案,有副作用)
ALTER SYSTEM SET cursor_sharing = FORCE SCOPE=BOTH;
-- 强制将字面值替换为系统生成的绑定变量,可能引发 ACS 问题
-- 2. 根本方案:改代码用绑定变量
-- 3. 检查未共享的 SQL
SELECT sql_id, executions, sql_text
FROM v$sql
WHERE parsing_schema_name = 'YOURAPP'
AND plan_hash_value = 0
ORDER BY sql_id
FETCH FIRST 100 ROWS ONLY;
坑 3:PGA 设置过大导致 OOM
现象:实例崩溃,alert log 报 ORA-04030: out of process memory。
原因:PGA_AGGREGATE_TARGET 设置过高,叠加 SGA 后超过物理内存。
解决:
-- 1. 检查 PGA 实际使用
SELECT SUM(pga_alloc_mem)/1024/1024/1024 AS "PGA Allocated(GB)"
FROM v$process;
-- 2. 限制单个 SQL 工作区上限
ALTER SYSTEM SET "_pga_max_size" = 2147483648; -- 2 GB
-- 3. 调整 PGA_AGGREGATE_TARGET
ALTER SYSTEM SET pga_aggregate_target = 2G;
坑 4:Buffer Cache 过小导致 cache hit 低
现象:AWR 中 Buffer Cache Hit Ratio < 90%,db file sequential read 等待高。
解决:
-- 1. 查看命中率
SELECT 1 - (physical.value - direct.value - log.value) / buffer.value AS "Cache Hit Ratio"
FROM v$sysstat physical, v$sysstat direct, v$sysstat log, v$sysstat buffer
WHERE physical.name = 'physical reads'
AND direct.name = 'physical reads direct'
AND log.name = 'physical reads direct (lob)'
AND buffer.name = 'session logical reads';
-- 2. 查看 Buffer Cache 顾问建议
SELECT size_for_estimate/1024/1024 AS "Size(MB)",
size_factor, estd_physical_read_time
FROM v$db_cache_advice
WHERE buffer_pool = 'DEFAULT';
-- 3. 增大 Buffer Cache
ALTER SYSTEM SET db_cache_size = 16G;
坑 5:Shared Pool 过大反而性能下降
现象:把 Shared Pool 调到 32 GB 后,library cache latch 争用反而增加。
原因:Shared Pool 越大,hash chain 越长,latch 争用概率越高。
解决:Shared Pool 不是越大越好,经验上限 4-8 GB。超过时应优化 SQL 共享而非加内存。
最佳实践总结
- 生产环境必用 ASMM + HugePages,禁用 AMM
- PGA 与 SGA 比例:OLTP 1:4,DSS 1:1
- SGA_TARGET 不超过物理内存 70-80%,留出 OS 与 PGA 空间
- 必须用绑定变量,并监控
v$sql中相似 SQL 数量 - 定期收集 AWR 报告,关注 Top 等待事件
- Shared Pool 控制在 4-8 GB,超过就优化 SQL 而非加内存
- Redo Log Buffer ≥ 64 MB,避免 LGWR 频繁写
- 启用 Large Pool(共享服务器、并行查询、RMAN 场景)
- 保留 1-2 GB 内核缓冲给 OS,避免 swap
- 23ai 新库用 Unified Memory,简化管理
9. 常见问题 FAQ
Q1: SGA_TARGET 和 SGA_MAX_SIZE 的区别?
SGA_TARGET:当前 ASMM 目标值,可在ALTER SYSTEM中动态调整,上限是SGA_MAX_SIZESGA_MAX_SIZE:SGA 上限,需重启实例才能修改- 建议:
SGA_MAX_SIZE设为物理内存上限的 70%,SGA_TARGET初始设为预期值,留出扩展空间
Q2: PGA_AGGREGATE_TARGET 和 PGA_AGGREGATE_LIMIT 的区别?
PGA_AGGREGATE_TARGET:目标值,Oracle 尽量不超过(软限制)PGA_AGGREGATE_LIMIT(12c+):硬限制,超过时会中止最耗 PGA 的会话- 推荐:
LIMIT = 2 * TARGET或物理内存的 1.5 倍,取较小者
Q3: 如何判断是否需要增加 Buffer Cache?
-- 1. 看命中率(< 95% 值得考虑)
SELECT 1 - SUM(decode(name, 'physical reads', value, 0)) /
SUM(decode(name, 'session logical reads', value, 0)) AS hit_ratio
FROM v$sysstat WHERE name IN ('physical reads', 'session logical reads');
-- 2. 看顾问建议
SELECT size_factor, estd_physical_read_factor
FROM v$db_cache_advice WHERE buffer_pool = 'DEFAULT';
-- estd_physical_read_factor < 1.0 说明增大有收益
Q4: Shared Pool Free Memory 很大但还是 latch 争用?
这说明碎片化严重,而非内存不够。
-- 查看碎片
SELECT pool, name, bytes/1024/1024 AS "MB"
FROM v$sgastat
WHERE pool = 'shared pool' AND name = 'free memory';
-- 刷共享池(谨慎,会强制所有 cursor 重新解析)
ALTER SYSTEM FLUSH SHARED_POOL;
Q5: AMM 与 HugePages 不兼容如何取舍?
生产环境选 HugePages:
- HugePages 提升 SGA 访问性能 5-15%
- AMM 的便利性不如性能重要
- 19c 起 Oracle 官方文档明确推荐生产用 ASMM + HugePages[1]
10. 参考资料
[1] Oracle Database 19c 概念文档,第 15 章 Memory Architecture: https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/memory-architecture.html
[2] Oracle Database 23ai 概念文档,第 17 章 Memory Architecture(含 MGA / Unified Memory): https://docs.oracle.com/en/database/oracle/oracle-database/23/cncpt/memory-architecture.html
[3] Oracle Database Memory Architecture 官方文档(含 LRU/Write List 工作机制): https://docs.oracle.com/cd/A58617_01/server.804/a58227/ch_mem.htm
[4] 周同学带您玩 AI,《解析 Oracle 数据库架构:实例、内存和进程的完美结合》,墨天轮: https://www.modb.pro/db/1822855013329285120
[5] 墨天轮,《Oracle 体系结构概览(二)》: https://www.modb.pro/db/104874
[6] Oracle Database Reference 19c,初始化参数文档: https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/
[7] Oracle Database Performance Tuning Guide 19c,内存调优章节: https://docs.oracle.com/en/database/oracle/oracle-database/19/tgdba/
相关文章