Shared Pool 深度解析

Shared Pool 深度解析

适用版本:Oracle Database 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

Shared Pool 是 SGA 中缓存 SQL、PL/SQL、数据字典等共享对象的内存区[1]。

核心子组件

子组件作用
Library CacheSQL/PL/SQL 解析结果、执行计划
Data Dictionary Cache数据字典缓存(rowcache)
Result Cache查询结果缓存
Reserved Pool大块内存预留

2. Library Cache

2.1 作用

缓存 SQL/PL/SQL 的解析树、执行计划,避免重复解析[2]。

2.2 缓存对象

对象类型说明
SQL 游标SQL 语句的解析结果
PL/SQL 对象存储过程、函数、包、触发器
Java 类Java 存储过程
Object Definition表/索引/视图定义

2.3 Library Cache 命中率

SELECT 
  SUM(gets) AS total_gets,
  SUM(gethits) AS hits,
  ROUND(SUM(gethits)/NULLIF(SUM(gets),0)*100, 2) AS hit_pct
FROM v$librarycache;
-- 健康标准:> 95%

2.4 SQL 共享条件

SQL 语句要共享执行计划,必须满足[3]:

  1. 文本完全一致(包括空格、大小写)
  2. 引用对象相同(所有者、对象名)
  3. 绑定变量类型/长度一致
  4. 会话环境一致(NLS、优化器模式等)
-- 这两条 SQL 不共享:
SELECT * FROM emp WHERE id=1;
SELECT * FROM emp WHERE id=2;

-- 这两条 SQL 共享:
SELECT * FROM emp WHERE id=:1;

2.5 查看库缓存中的 SQL

-- 查找 SQL 文本和执行次数
SELECT 
  sql_id,
  parsing_schema_name,
  executions,
  parse_calls,
  buffer_gets,
  sql_text
FROM v$sql
WHERE parsing_schema_name='SCOTT'
ORDER BY executions DESC;

-- 查找未共享的相似 SQL
SELECT sql_text, COUNT(*) 
FROM v$sql 
GROUP BY sql_text 
HAVING COUNT(*) > 5
ORDER BY COUNT(*) DESC;

3. Data Dictionary Cache(Row Cache)

3.1 作用

缓存数据字典信息(如表定义、用户权限等)。

3.2 查看

SELECT 
  parameter,
  gets,
  getmisses,
  ROUND(getmisses/NULLIF(gets,0)*100, 2) AS miss_pct
FROM v$rowcache
WHERE gets > 0;
-- 健康标准:miss_pct < 15%

4. Result Cache

4.1 作用

缓存查询结果,重复查询直接返回缓存。

4.2 配置

SHOW PARAMETER result_cache_mode;
-- MANUAL: 需显式 Hint
-- FORCE: 自动缓存所有查询

-- 启用 Result Cache
ALTER SYSTEM SET result_cache_mode=MANUAL SCOPE=BOTH;
ALTER SYSTEM SET result_cache_max_size=256M SCOPE=BOTH;

4.3 使用

-- 显式 Hint
SELECT /*+ RESULT_CACHE */ * FROM large_table WHERE id=1;

-- 函数结果缓存
CREATE OR REPLACE FUNCTION get_salary(p_id NUMBER) 
  RETURN NUMBER 
  RESULT_CACHE
IS
  v_sal NUMBER;
BEGIN
  SELECT salary INTO v_sal FROM employees WHERE id=p_id;
  RETURN v_sal;
END;

4.4 查看

SELECT 
  type, 
  status, 
  count(*) AS cnt
FROM v$result_cache_objects
GROUP BY type, status;

5. Reserved Pool

5.1 作用

为大块内存分配(> 4400 字节)预留空间,避免 Shared Pool 碎片化。

5.2 配置

SHOW PARAMETER shared_pool_reserved_size;
-- 默认 Shared Pool 的 5%

ALTER SYSTEM SET shared_pool_reserved_size=100M SCOPE=BOTH;

6. Shared Pool 管理

6.1 大小配置

SHOW PARAMETER shared_pool_size;

-- 估算需求
SELECT 
  SUM(bytes)/1024/1024 AS shared_pool_mb
FROM v$sgastat
WHERE pool='shared pool';

6.2 查看空间使用

-- 子组件占用
SELECT 
  name, 
  bytes/1024/1024 AS mb,
  ROUND(bytes/SUM(bytes) OVER()*100, 2) AS pct
FROM v$sgastat 
WHERE pool='shared pool'
ORDER BY bytes DESC;

6.3 刷新 Shared Pool

-- 谨慎使用:会导致所有 SQL 重新解析
ALTER SYSTEM FLUSH SHARED_POOL;

7. 常见视图

-- Library Cache 详细信息
SELECT 
  namespace,
  gets,
  gethits,
  pins,
  pinhits,
  reloads,
  invalidations
FROM v$librarycache;

-- 共享游标
SELECT sql_id, child_number, sql_text, executions
FROM v$sql
WHERE sql_text LIKE '%employees%';

-- Library Cache 锁
SELECT sid, type, id1, id2, lmode, request 
FROM v$lock 
WHERE type IN ('LA','LP','LC','LR','LS','LT','LU','LV','LW','LX');

-- 等待事件
SELECT event, total_waits, time_waited
FROM v$system_event
WHERE event LIKE 'library cache%';

8. 常见坑与排错

8.1 ORA-04031: Shared Pool 空间不足

现象

ORA-04031: unable to allocate 4096 bytes of shared memory ("shared pool",...)

排查

-- 查看 Shared Pool 详情
SELECT name, bytes/1024/1024 AS mb 
FROM v$sgastat 
WHERE pool='shared pool' 
ORDER BY bytes DESC;

-- 查看 Library Cache 锁
SELECT sid, event, sql_id 
FROM v$session 
WHERE event LIKE 'library cache%';

修复

-- 1. 增大 Shared Pool
ALTER SYSTEM SET shared_pool_size=2G SCOPE=BOTH;

-- 2. 临时刷新
ALTER SYSTEM FLUSH SHARED_POOL;

-- 3. 根本解决:使用绑定变量

8.2 硬解析过多

现象:Library Cache 命中率低,parse time elapsed 高。

SELECT name, value 
FROM v$sysstat 
WHERE name IN ('parse count (total)', 'parse count (hard)', 'parse time elapsed');
-- parse count (hard) 应 < parse count (total) 的 5%

修复

  • 使用绑定变量
  • 设置 CURSOR_SHARING=FORCE(临时方案)
  • 优化应用代码

8.3 Library Cache Lock / Pin

现象:DDL 操作卡住,无法重编译对象。

-- 查找阻塞者
SELECT 
  s.sid, s.serial#, s.username, s.program,
  l.type, l.lmode, l.request
FROM v$session s
JOIN v$lock l ON s.sid = l.sid
WHERE l.type IN ('LA','LP','LC','LT','LU','LV','LW','LX');

-- 找到后终止
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;

8.4 ORA-04045: errors during recompilation/revalidation

现象:重编译对象报错。

原因:对象上有 Library Cache Lock。

修复:找到并终止持锁会话。


9. 最佳实践

  1. 使用绑定变量:减少硬解析
  2. Shared Pool ≥ 1GB:保证缓存充足
  3. 避免 SHARED_POOL 刷新:除非紧急
  4. 定期监控命中率:Library Cache > 95%
  5. 使用 CURSOR_SHARING=EXACT(默认):避免执行计划偏差
  6. PL/SQL 包封装:减少对象依赖
  7. 避免 DDL 高峰期:减少 Library Cache 失效

10. 参考资料

[1] Oracle Database Concepts 19c, “Shared Pool” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/memory-architecture.html

[2] Oracle Database Administrator’s Guide 19c, “Managing the Shared Pool” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/managing-memory.html

[3] AskTOM, “Library Cache and SQL Sharing” https://asktom.oracle.com/pls/apex/f?p=100:1:0