ORA-1555エラー解説:原因、対策、そして予防まで

Oracle Master Silver

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. 発生を防ぐ運用のベストプラクティス

  1. UNDO表領域の監視
    定期的にUNDOの使用状況を確認します。sqlコードをコピーするSELECT TABLESPACE_NAME, BYTES/1024/1024 AS MB FROM DBA_DATA_FILES WHERE TABLESPACE_NAME = 'UNDOTBS1';
  2. クエリのリファクタリング
    長時間実行されるクエリは分割し、複数の小さなトランザクションにします。
  3. 適切なインデックス設計
    高頻度でアクセスされるデータにインデックスを付加します。
  4. UNDO表領域の自動拡張設定
    表領域が限界を超えないように自動拡張を有効にします。

6. ケーススタディ:実際のトラブルとその解決

ケース1: ロングクエリによるORA-1555

問題:
夜間バッチ処理で発生。クエリ実行時間が1時間を超え、UNDOデータが不足。

解決策:

  1. UNDO表領域を4GBに拡張。
  2. クエリを1万行単位で分割。
  3. UNDO_RETENTIONを1800秒に調整。

ケース2: トランザクション競合

問題:
日中のピーク時間にトランザクションが過剰発生し、ORA-1555が多発。

解決策:

  1. インデックスを再構築し、競合を減少。
  2. 更新トランザクションをバッチ化して負荷を分散。

まとめ

「ORA-1555: スナップショットが古すぎます」エラーは、UNDOデータやクエリ設計の問題に起因します。以下の対策を講じることで、エラーの発生を最小限に抑えることが可能です。

  1. UNDO表領域のサイズ最適化
  2. UNDO_RETENTIONの調整
  3. 長時間クエリの分割設計
  4. 監視とプロアクティブな管理

データベースの安定性を高めるために、これらのポイントを運用に取り入れてみてください!

[参考]
Oracle Databaseパフォーマンス・チューニング・ガイド 19c

コメント

タイトルとURLをコピーしました