
Oracle 数据库共享池内存结构深度解析:Chunk 类型与 x$ksmsp 视图
在 Oracle 数据库的共享池内存管理中,Chunk 是最基本的分配单元,而 x$ksmsp 视图则是深入洞察共享池内部状态的终极工具。下面我们将详细解析这些核心概念。
1. Chunk 类型详解
在共享池中,Chunk 根据其用途和生命周期被分为几种重要类型。这些类型反映了 Oracle 内存管理的精细策略。
官方/专业解释
共享池中的 Chunk 主要分为以下几类:
-
FREE (空闲块)
- 定义:当前未被任何对象使用的内存块,位于空闲列表(Free List)上,可供分配。
- 特性:当新的内存请求到来时,内存管理器首先在这些块中寻找合适大小的空间。
-
RCR (Recreatable - 可重建块)
- 定义:用于存储那些可以被自动重建的对象内容,主要是库缓存(Library Cache) 中的对象,如 SQL 语句、PL/SQL 代码的执行计划、解析树等。
- 特性:这是共享池中最大的一类。当内存不足时,这些块可以根据需要被 aged out(老化移出),之后如果需要,可以通过重新解析 SQL 或重新加载包来重建。
- 老化机制:基于 LRU(最近最少使用)算法。
-
PRM (Permanent - 永久块)
- 定义:用于存储那些不能被轻易重建的关键数据结构,主要是数据字典缓存(Row Cache) 中的信息,如表、列、用户权限的定义等。
- 特性:这些块对于数据库的运行至关重要,通常不会被 aged out。强制清除它们可能导致性能问题或错误。
-
FREEABLE (可释放块)
- 定义:一种特殊类型的块,它当前已被分配,但允许在需要时被释放回空闲列表。它处于 RCR 和 FREE 之间的一种状态。
-
保留堆中的块
- 定义:位于
shared_pool_reserved_size分配的保留堆中的块。它们也有 FREE、RCR、PRM 等状态,但专用于大内存分配(大于_shared_pool_reserved_min_alloc参数值,通常为 4400 字节)。
- 定义:位于
通俗解释
想象共享池是一个大型自助仓储中心,Chunk 就是里面一个个不同大小的仓储单元。
- FREE 块:空置的、待出租的仓储单元。管理员手上有清单(Free List),知道哪些是空的。
- RCR (可重建) 块:存放了可替代物品的单元,比如从宜家买的家具。如果仓库空间不够了(内存压力),管理员可以把这些家具拆了(aged out)腾地方。以后客户需要时,可以按照说明书(重做日志/SQL文本)重新组装(重新解析)一个。
- PRM (永久) 块:存放了传家宝或重要文件的单元。这些东西独一无二,不能丢弃。管理员绝不会为了腾空间而扔掉它们。
- 保留区中的块:专门为存放超大件物品(如游艇、汽车)准备的 VIP 区域。普通区域(主堆)的小格子放不下这些东西,强行放入会打乱所有布局(导致碎片化)。所以大件物品直接送到VIP区存放。
2. x$ksmsp 视图:共享池的 “X 光片”
x$ksmsp 是一个底层的、动态的性能视图,它直接暴露了共享池中每一个 Chunk 的原始信息。查询它就像给共享池拍了一张高分辨率的 X 光片,可以看清其内部每一个"细胞"的状态。
警告:因为查询该视图需要遍历共享池内部结构并可能持有闩锁(Latch),所以在高负载的生产系统上极其谨慎地使用,最好在技术支持或负载极低时进行。
核心字段解释
| 字段名 (Column) | 数据类型 | 描述 | 通俗解释 |
|---|---|---|---|
| KSMCHCOM | VARCHAR2 | Comment,注释字段。通常描述了该 Chunk 的用途或所属的组件(如 “sql area”, “free memory”, “perm allocation”)。 | 仓储单元上贴的标签,写着"存放家具"或"空置"。 |
| KSMCHCLS | VARCHAR2 | Class,Chunk 的类别。这是最重要的字段之一,直接表明 Chunk 的类型。 | 仓储单元的类型牌:“FREE”, “R-free”, “RCR”, “PRM”, “FREEABLE” |
| KSMCHSIZ | NUMBER | Size,Chunk 的大小(以字节为单位)。 | 仓储单元的面积(平方米)。 |
| KSMCHPTR | RAW(4 | 8) | Pointer,指向该 Chunk 起始地址的原始内存指针。 |
| KSMCHPAR | RAW(4 | 8) | Parent Pointer,指向父 Chunk 的指针。对于子堆(Subheap)中的 Chunk,此字段指向其父堆。 |
3. 深入诊断:相关查询 SQL 命令
以下 SQL 命令利用 x$ksmsp 视图来深入分析共享池。
查询 1:按 Chunk 类型统计汇总
此查询展示了共享池的整体健康状况,显示了每种类型的 Chunk 有多少个,以及它们占了多大空间。
SELECT
KSMCHCLS AS chunk_class,
COUNT(*) AS chunk_count,
ROUND(SUM(KSMCHSIZ) / 1024 / 1024, 2) AS total_size_mb,
ROUND(AVG(KSMCHSIZ) / 1024, 2) AS avg_size_kb,
ROUND(MIN(KSMCHSIZ) / 1024, 2) AS min_size_kb,
ROUND(MAX(KSMCHSIZ) / 1024, 2) AS max_size_kb
FROM x$ksmsp
GROUP BY KSMCHCLS
ORDER BY total_size_mb DESC;
结果分析:
- 如果
free类型的chunk_count非常高但avg_size_kb非常小,表明共享池碎片化严重。有很多小空闲块,但可能无法满足大内存分配请求。 R-free和free的总大小代表了总的可用空闲内存。recr和freeable是主要的可管理内存。
查询 2:按分配用途(Comment)统计内存使用
这个查询告诉你共享池的内存都被哪些模块或对象用掉了,帮你找到"内存大户"。
SELECT
KSMCHCOM AS component,
KSMCHCLS AS chunk_class,
COUNT(*) AS chunk_count,
ROUND(SUM(KSMCHSIZ) / 1024 / 1024, 2) AS size_mb
FROM x$ksmsp
WHERE KSMCHCOM NOT LIKE '%free%' -- 过滤掉空闲内存,只看已使用的
GROUP BY KSMCHCOM, KSMCHCLS
HAVING SUM(KSMCHSIZ) > 1 * 1024 * 1024 -- 只显示大于1MB的组件
ORDER BY size_mb DESC;
结果分析:你可能发现 "sql area" 占用了大量空间,这表明应用发出了很多不同的 SQL 语句,可能需要优化应用使用绑定变量。
查询 3:查找最大的空闲 Chunk
最大的空闲 Chunk 的大小决定了共享池能否满足大内存分配请求而不产生 ORA-04031 错误。
SELECT
KSMCHSIZ / 1024 AS size_kb,
KSMCHCLS,
KSMCHCOM
FROM x$ksmsp
WHERE KSMCHCLS IN ('free', 'R-free')
ORDER BY KSMCHSIZ DESC;
结果分析:如果最大空闲块的大小(例如 200KB)远小于 _shared_pool_reserved_min_alloc 参数值(默认 ~4400 bytes),但总的空闲内存还很多,这就是典型的内存碎片化现象。大请求无法获得连续空间,即使总空闲空间足够。
查询 4:检查保留池的使用情况
专门查看保留堆(Reserved Pool)的状态。
SELECT
KSMCHCLS,
COUNT(*) AS chunks,
ROUND(SUM(KSMCHSIZ) / 1024 / 1024, 2) AS size_mb,
ROUND(SUM(KSMCHSIZ) / COUNT(*), 2) AS avg_bytes_per_chunk
FROM x$ksmsp
WHERE KSMCHCLS LIKE 'R-%' -- R-free, R-rcre, R-perm
GROUP BY KSMCHCLS;
4. 管理命令与优化建议
基于上述诊断结果,可以采取以下管理措施:
-
缓解碎片化/避免 ORA-04031:
- 刷新共享池(最后手段):
ALTER SYSTEM FLUSH SHARED_POOL;。这会清除所有RCR对象,强制重新解析,短期内影响性能。 - 增加保留池大小: 如果
R-free经常为0或很小,可以增大shared_pool_reserved_size(通常设为shared_pool_size的 5%-10%)。ALTER SYSTEM SET shared_pool_reserved_size = 100M; - 固定重要对象: 使用
DBMS_SHARED_POOL.KEEP将频繁使用的大包或游标固定,防止它们被换出和换入,从而减少碎片。EXEC DBMS_SHARED_POOL.KEEP('SCOTT.LARGE_PKG', 'P');
- 刷新共享池(最后手段):
-
优化库缓存:
- 使用绑定变量: 这是最重要的优化!减少硬解析和不同 SQL 的数量,从根本上减少
sql area的内存消耗。 - 调整共享池大小: 如果库缓存命中率低且确实需要更大空间。
ALTER SYSTEM SET shared_pool_size = 2G; -- 在ASMM下也可设置
- 使用绑定变量: 这是最重要的优化!减少硬解析和不同 SQL 的数量,从根本上减少
-
监控与预警:
- 定期运行查询 1 和查询 3,监控碎片化趋势和最大空闲块大小。
- 设置预警,当
v$sgastat中free memory低于一定阈值或v$shared_pool_reserved的REQUEST_MISSES持续增加时发出警报。
通过结合 x$ksmsp 提供的微观视图和诸如 v$librarycache、v$rowcache、v$sgastat 等宏观视图,你可以构建一个完整的共享池健康模型,从而进行精准的性能调优和故障诊断。
欢迎关注我的公众号《IT小Chen》
22

被折叠的 条评论
为什么被折叠?



