運用時に発生するエラー

ORA-01555: スナップショットが古すぎます: ロールバック・セグメント番号 xxx、名前"yyy"が小さすぎます

読み取り一貫性に関する問題。特にフェッチ・アクロス・コミット処理において発生する。

原因

UNDO 領域の不足(手動によるロールバックセグメントの運用の場合)
大きな結果セットをもつ SELECT を実行すると読み取り一貫性により、SELECT 実行以降に更新されているレコードの以前の情報を ロールバック・セグメント(UNDO)から取り出さなければならない。
しかし、更新前の情報をもつロールバックセグメントが一巡して情報を上書きされると SELECT 実行時の結果セットのスナップショット(その瞬間の映像)が損失している状態になりスナップショットを再現できない。
ここで重要なのは、エラーが発生するプログラム自身が使用するロールバックセグメントではなく、SELECT で取得した結果セットを更新している、あるサブプログラムが使用しているロールバックセグメントである点である。(ORA-01555 エラーが発生するのは、そのロールバックセグメントのはず)
そして多くの場合、そのあるサブプログラムとは、そのプログラム自身である事が多い。

対応 8i 以前

大きな専用のロールバックセグメントを用意して割り当てる。(発生確率を低下させる)
注意 割り当てはトランザクション単位で解除される。
並行して別の大量更新処理が発生する場合も同様の処理を施す。

対応 9i〜

自動 UNDO 運用を使用する。自動拡張に設定している場合には UNDO_RETENTION 初期化パラメータで指定時間(秒)までは保証される。その分のディスク容量は必要、不用意な SQL による UNDO 領域の異常増加による DISK FULL に注意する。 自動拡張に設定していない場合には「努力目標」となり再利用されてしまうことがある。

対応 10g

自動 UNDO 運用を使用して UNDO_RETENTION 初期化パラメータとともに UNDO 表領域の GURANTEE 属性 Oracle 10g の使用を検討する。

CREATE UNDO TABLESPACE <undo_tablespace_name>
....
RETENTION GUARANTEE;

GUARANTEE を設定することで UNDO_RETENTION 初期化パラメータの値は「努力目標」ではなく「保証」されることになるが、 代わりに UNDO 領域を確保できない場合には(期限切れとなるまで解放されないために) UNDO を必要とする処理はエラーになる。

原因

ブロックのクリーンアウト、トランザクションスロットの枯渇
COMMIT 回数の少ない場合や処理するデータブロックが広範囲にわたる大きなトランザクションは 遅延ブロッククリーンアウト というギミックによって COMMIT 処理が高速化されている。 このときに ITL から UNDO 情報を取り出してブロック内の システム変更番号(SCN) が遅延して更新(クリーンアウト)されるという仕組みが ORA-01555 〜エラーの原因になることがある。
また、単純にトランザクションスロット数が自体が不足してしまっていることもある。

対応

処理開始時にデータやインデックスをフェッチ(フルスキャン)してテーブルとインデックスのデータブロックを継ぎ接ぎ? の無い状態にする(=クリーンアウト)。

SELECT /*+ FULL(t) */ COUNT(*) FROM table_name t;
SELECT /*+ INDEX_FFS(t index_name) */ COUNT(*) table_name t;
-- index_name は省略可能

トランザクションスロット数を増やす(TRANSACTIONS 初期化パラメータ:ロールバックセグメントの数を増加させる)。

 

処理アプローチの変更(解決策ではない)

パーティション表 が使用できる場合にはパーティションプルーニングを使用することで処理を分割する。(それをパラレルに動作させているとトランザクションスロット数は比例増加する)



一覧ページへ戻る

OTN (Oracle Technology Network)によるエラーメッセージによる情報だけでは、対処に困ったエラーについてのプラクティスです。
ベスト・プラクティスというわけではないので、書いてあることに固執しないで広い視野でエラー対応してください。

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ Oracle のライセンスがわからない…
Oracle Direct (ネットで聞いても最後はここで要確認)