タイトル: 共有プール
SEOタイトル: Oracle Shared Pool (共有プール) 完全ガイド|Library Cache / ORA-04031 / DBMS_SHARED_POOL.KEEP
| この記事の要点 |
|
共有プールとは
共有プール (Shared Pool) は Oracle Database の SGA (System Global Area) を構成するメモリ領域の 1 つで、SQL や PL/SQL の解析済み実行計画、データディクショナリ情報、結果キャッシュなどを保持します。同じ SQL を 2 度目以降に実行するとき、解析(パース)を省略できるため、OLTP 系システムでは性能の生命線となります。
SGA の中での位置づけ
| SGA 構成要素 | 役割 | 関連パラメータ |
|---|---|---|
| Shared Pool | SQL/PLSQL 解析結果、データディクショナリ | SHARED_POOL_SIZE |
| Database Buffer Cache | データブロックのキャッシュ | DB_CACHE_SIZE |
| Redo Log Buffer | REDO ログのバッファ | LOG_BUFFER |
| Large Pool | RMAN / 並列 / UGA 用大型割当 | LARGE_POOL_SIZE |
| Java Pool | Java VM 用 | JAVA_POOL_SIZE |
| Streams Pool | Streams / GoldenGate 用 | STREAMS_POOL_SIZE |
共有プールの内部構成
1. Library Cache (ライブラリキャッシュ)
SQL 文・PL/SQL ブロック・パッケージ・トリガなどの解析済み形式と実行計画を保持。同一 SQL の 2 回目以降はソフトパースで済むため、ハードパースを大幅削減できます。
-- ライブラリキャッシュの統計
SELECT namespace, gets, gethits, gethitratio, pins, pinhits, pinhitratio, reloads, invalidations
FROM v$librarycache;
-- 共有 SQL を確認
SELECT sql_id, executions, parse_calls, loads, sql_text
FROM v$sqlarea
WHERE executions > 100
ORDER BY executions DESC FETCH FIRST 20 ROWS ONLY;
2. Data Dictionary Cache (Row Cache)
SYS スキーマのメタ情報(テーブル定義、ユーザー権限、表領域情報など)をキャッシュ。SQL 解析時に大量参照されるため、Library Cache と相互依存しています。
3. Server Result Cache / PL/SQL Function Result Cache
クエリ結果や PL/SQL 関数の戻り値そのものをキャッシュ。同一クエリの再実行を SQL 実行ごと省略できます (Oracle 11g+)。
-- Result Cache 有効化
ALTER SYSTEM SET RESULT_CACHE_MAX_SIZE = 100M;
ALTER SYSTEM SET RESULT_CACHE_MODE = MANUAL;
-- ヒント指定でキャッシュ利用
SELECT /*+ RESULT_CACHE */ dept_id, COUNT(*) FROM employees GROUP BY dept_id;
-- 利用状況
SELECT name, value FROM v$result_cache_statistics;
サイズ管理: AMM / ASMM / 手動
| 方式 | パラメータ | 動作 |
|---|---|---|
| AMM (Automatic Memory Management) | MEMORY_TARGET | SGA + PGA を Oracle が自動配分 (11g+) |
| ASMM (Automatic Shared Memory Management) | SGA_TARGET | SGA 内の各プールを自動配分 (10g+) |
| 手動 | SHARED_POOL_SIZE 等 | 明示指定 |
-- 現在の設定値を確認
SHOW PARAMETER memory_target
SHOW PARAMETER sga_target
SHOW PARAMETER shared_pool_size
-- ASMM で共有プール下限を保証 (Oracle が縮小しないように)
ALTER SYSTEM SET SHARED_POOL_SIZE = 2G SCOPE=SPFILE;
ALTER SYSTEM SET SGA_TARGET = 8G SCOPE=SPFILE;
-- SGA 全体内訳
SELECT pool, name, ROUND(bytes/1024/1024, 2) mb
FROM v$sgastat
WHERE pool = 'shared pool'
ORDER BY bytes DESC FETCH FIRST 20 ROWS ONLY;
ORA-04031: Shared Pool 枯渇エラー
共有プール内で連続した空きメモリが確保できないときに発生する代表的なエラー:
ORA-04031: unable to allocate 4096 bytes of shared memory
("shared pool","SELECT ...","SQLA","tmp")
主な原因と対処:
| 原因 | 対処 |
|---|---|
| バインド変数を使わずリテラル SQL を量産(共有プールがゴミだらけ) | バインド変数化 / CURSOR_SHARING=FORCE |
| 大きな PL/SQL パッケージが頻繁にエージアウト | DBMS_SHARED_POOL.KEEP で固定化 |
| 共有プール自体が小さい | SHARED_POOL_SIZE / SGA_TARGET 拡大 |
| 断片化 | ALTER SYSTEM FLUSH SHARED_POOL(一時しのぎ) |
DBMS_SHARED_POOL.KEEP による固定化
大きな PL/SQL や頻繁に使われるパッケージを共有プールに常駐させ、エージアウトを防ぎます:
-- パッケージを共有プールにピン留め
EXEC DBMS_SHARED_POOL.KEEP('SCOTT.MY_PACKAGE', 'P');
-- カーソル (SQL) を固定 (引数は ADDRESS, HASH_VALUE)
EXEC DBMS_SHARED_POOL.KEEP('20000000A,3151942139', 'C');
-- 解除
EXEC DBMS_SHARED_POOL.UNKEEP('SCOTT.MY_PACKAGE', 'P');
-- 固定済オブジェクト確認
SELECT owner, name, type, kept FROM v$db_object_cache WHERE kept = 'YES';
FLUSH SHARED_POOL(緊急時のみ)
-- 共有プール全体をフラッシュ (本番では推奨しない)
ALTER SYSTEM FLUSH SHARED_POOL;
-- 結果キャッシュのみフラッシュ
EXEC DBMS_RESULT_CACHE.FLUSH;
-- バッファキャッシュのフラッシュ (検証用)
ALTER SYSTEM FLUSH BUFFER_CACHE;
フラッシュ直後は全 SQL がハードパースとなり、CPU 急騰の可能性。本番では避け、根本対策(バインド変数化、SGA 増強)を優先します。
監視ビューまとめ
| ビュー | 用途 |
|---|---|
v$sgastat | SGA 内訳 |
v$shared_pool_advice | 共有プールサイズ最適化助言 |
v$librarycache | Library Cache ヒット率 |
v$rowcache | Data Dictionary Cache |
v$db_object_cache | キャッシュされているオブジェクト |
v$sqlarea | 共有 SQL |
v$result_cache_statistics | Result Cache 統計 |
FAQ
Q: ASMM 環境でも SHARED_POOL_SIZE を明示すべき?
A: 値を設定すると下限値の保証になります。OLTP では下限を設けるのが定石です。
Q: バインド変数化が難しい古いアプリへの対処
A: CURSOR_SHARING=FORCE でリテラルを自動バインド化。ただし実行計画が悪化することもあるため検証必須。
Q: AWR レポートで共有プールが悪いか判断する観点
A: 「Library Hit %」95% 未満、「Soft Parse %」95% 未満、Top Waits に library cache: mutex X / cursor: pin S wait on X が並ぶなら共有プールが原因の可能性大。