Oracleデータベースを運用している方であれば、**「ORA-1555: スナップショットが古すぎます」**というエラーに頭を抱えた経験があるかもしれません。このエラーは、長時間のクエリ実行中に「過去のデータ」を参照できなくなる場合に発生します。
なぜこのエラーが発生するのか?
どのように対策すればよいのか?
この記事を読めば、ORA-1555エラーの全容を把握し、実践的な解決策を得られます。
1. 読み取り一貫性とは?
Oracleデータベースでは、複数のトランザクションが同時に実行されていても、各クエリが開始時点のデータ状態を一貫して参照できるように設計されています。
用語解説
- UNDOセグメント
データ変更前の状態を記録する領域。
→ 過去のデータを「タイムマシン」のように再現します。 - スナップショット
クエリ実行開始時のデータ状態。
図1: 読み取り一貫性の仕組み
+------------------------+ SELECT文 +------------------------+
| データブロック (最新) | -----------------> | クエリ開始時のデータ |
| | | (UNDOセグメントから復元)|
+------------------------+ +------------------------+
2. ORA-1555エラーの原因
ORA-1555エラーは、以下の状況で発生します。
1. UNDOデータの不足
UNDO表領域が小さい場合、長時間実行されるクエリが必要とする過去データが上書きされてしまいます。
図2: UNDOデータ不足の例
+---------+------------------+------------------+
| 時間 | UNDOデータ | クエリの状態 |
+---------+------------------+------------------+
| 0分 | A, B, C | クエリ開始 |
| 10分 | D, E, F (A消失) | Aが必要 |
+---------+------------------+------------------+
2. ロングクエリ
実行時間が長いクエリがUNDOデータを大量に消費し、エラーを引き起こします。
3. 表領域設計の不備
UNDO表領域が自動拡張されていない場合や、サイズが小さすぎる場合に起こります。
4. トランザクションの過剰
同時に多数のトランザクションが発生し、UNDOデータが逼迫することでエラーが発生します。
3. 詳細な原因診断手順
エラーの原因を特定するために以下を実行します。
1. アラートログを確認
tail -f $ORACLE_BASE/diag/rdbms/<SID>/trace/alert_<SID>.log
2. UNDOの使用状況を分析
SELECT BEGIN_TIME, END_TIME, UNDOBLKS, TXNCOUNT, MAXQUERYLEN
FROM V$UNDOSTAT
WHERE BEGIN_TIME >= SYSDATE - 1;
3. 長時間クエリの特定
SELECT SID, SERIAL#, SQL_ID, TIME_REMAINING
FROM V$SESSION_LONGOPS
WHERE TIME_REMAINING > 0;
4. 効果的な対策とSQL例
1. UNDO表領域を適切に拡張する
UNDO表領域を増やすことで、必要なUNDOデータを確保します。
ALTER DATABASE DATAFILE '/path_to_undo/undotbs01.dbf' RESIZE 2G;
ALTER DATABASE DATAFILE '/path_to_undo/undotbs01.dbf' AUTOEXTEND ON MAXSIZE UNLIMITED;
2. UNDO_RETENTIONの調整
UNDOデータの保持期間を延長し、エラー発生を防ぎます。
ALTER SYSTEM SET UNDO_RETENTION = 1800; -- 30分
3. ロングクエリの最適化
長時間実行されるクエリを分割し、UNDOの消費を抑えます。
BEGIN
FOR i IN 1..10 LOOP
EXECUTE IMMEDIATE 'DELETE FROM large_table WHERE ROWNUM <= 1000';
END LOOP;
END;
4. アプリケーションの設計改善
トランザクションの分散や適切なインデックス設計を行い、競合を減らします。
5. 発生を防ぐ運用のベストプラクティス
- UNDO表領域の監視
定期的にUNDOの使用状況を確認します。sqlコードをコピーするSELECT TABLESPACE_NAME, BYTES/1024/1024 AS MB FROM DBA_DATA_FILES WHERE TABLESPACE_NAME = 'UNDOTBS1';
- クエリのリファクタリング
長時間実行されるクエリは分割し、複数の小さなトランザクションにします。 - 適切なインデックス設計
高頻度でアクセスされるデータにインデックスを付加します。 - UNDO表領域の自動拡張設定
表領域が限界を超えないように自動拡張を有効にします。
6. ケーススタディ:実際のトラブルとその解決
ケース1: ロングクエリによるORA-1555
問題:
夜間バッチ処理で発生。クエリ実行時間が1時間を超え、UNDOデータが不足。
解決策:
- UNDO表領域を4GBに拡張。
- クエリを1万行単位で分割。
- UNDO_RETENTIONを1800秒に調整。
ケース2: トランザクション競合
問題:
日中のピーク時間にトランザクションが過剰発生し、ORA-1555が多発。
解決策:
- インデックスを再構築し、競合を減少。
- 更新トランザクションをバッチ化して負荷を分散。
まとめ
「ORA-1555: スナップショットが古すぎます」エラーは、UNDOデータやクエリ設計の問題に起因します。以下の対策を講じることで、エラーの発生を最小限に抑えることが可能です。
- UNDO表領域のサイズ最適化
- UNDO_RETENTIONの調整
- 長時間クエリの分割設計
- 監視とプロアクティブな管理
データベースの安定性を高めるために、これらのポイントを運用に取り入れてみてください!
[参考]
Oracle Databaseパフォーマンス・チューニング・ガイド 19c
コメント