OracleのUNDOについて



🔄 UNDOとは?

Oracle Databaseは、以下の目的で「UNDOデータ(元の値)」を使用します:

  • トランザクションのロールバック

  • 一貫性のある読み取り(Read Consistency)

  • Oracle Flashback Query(過去の状態を参照する機能)

  • 障害時リカバリ


🧠 UNDOの仕組み

  • Oracleはデータを変更する前の**元の値(UNDOデータ)**を保存。

  • このUNDOは、トランザクションがコミットされるまで上書きされない

  • つまり、変更を**「お試し」感覚で行える**。

    • 他のユーザーには見えず、自分だけが確認できる。

    • 気に入れば COMMIT で確定。

    • 気に入らなければ ROLLBACK で元に戻せる。


💻 デモの例

  1. 2つのセッションで同じデータを確認(例:従業員ID 100 の給与)。

  2. 一方のセッションで給与を更新(UPDATE)。

  3. コミット前なので、他方のセッションでは元の給与が見える(一貫性のある読み取り)。

  4. COMMIT を実行すると、他のセッションでも変更が見えるようになる。


⚠️ 障害時のUNDOの役割

  • トランザクション中に:

    • ネットワーク障害やクライアントPCのクラッシュ

    • インスタンスクラッシュや SHUTDOWN ABORT の実行

  • こうした異常終了時は、自動的にUNDOデータでロールバックが行われる。


🧪 ロールバックの実例

  • 給与を1人だけ下げるつもりが、全従業員107人の給与を下げてしまった

  • ROLLBACK を使ってUNDOデータから変更前の状態に戻せた


⏳ UNDOデータの保持期間

  • UNDOはトランザクションが終了するまで必ず保持される。

  • 保持時間や容量は、データベースの負荷や設定に依存。


🔁 UNDOとREDOの役割の違い

項目UNDO(アンドゥ)REDO(リドゥ)
目的変更を取り消す(ロールバック)ため変更を再実行(ロールフォワード)するため
使用される時ユーザーがROLLBACKした時やセッション障害電源障害などで変更が失われたとき

🔄 UNDOの流れ

  • トランザクションが COMMIT される前 に、Oracleは UNDO情報(旧データ) を生成。

  • これは、ユーザーが変更を取り消す可能性に備えて保持される。

  • たとえば:

    • ROLLBACK をしたとき

    • セッションが異常終了したとき

  • OracleはこのUNDOを使って変更を元に戻す(ロールバック)


🔁 REDOの流れ

  • COMMIT 処理の際は、変更内容が REDOログファイル(ディスク上)に書き込まれたかを確認。

  • REDOログへの書き込みが完了すれば、たとえデータファイル(表の実データ)にまだ反映されていなくても

    • トランザクションは「確定済み(コミット済み)」と見なされる。

  • たとえば:

    • 電源障害でOSが落ちたが、REDOログに記録されていれば

    • 再起動時に、REDOログから変更を反映させてロールフォワードできる

✅ 読み取り一貫性

  • 読み取り一貫性(Read Consistent Queries) とは、
    クエリが開始された時点のデータを基準にして、一貫した結果を返す仕組みです。


🕒 具体例で説明:

  • たとえば、あなたのクエリが 時刻 T0 に開始 され、30分間実行されるとします。

  • 他のユーザーが 時刻 T5 にデータを更新してコミットしても、

  • あなたのクエリは、T0時点のデータをT30まで表示し続けます。

  • なぜなら、Oracleは Undo情報(変更前のデータ) を使って、
    クエリ開始時点の状態を再構築できるからです。


⚠️ 注意点:Undo情報の保持期間

  • ただし、他のユーザーが 頻繁にコミットしていると、

    • 古いUndo情報が上書きされて消える可能性があります。

  • この場合、あなたのクエリが更新された行に遅れてアクセスしたときに、

    • Undo情報がもう存在していないことがあります。

    • その結果、**ORA-01555: snapshot too old(スナップショットが古すぎる)**というエラーが発生する可能性があります。

✅ Oracle Flashback Query の使い方と仕組み


📌 Flashback Query とは?

  • Oracleの Flashback Query を使うと、過去のある時点のデータ(コミット済み) を取り出すことができます。

  • 他のフラッシュバック機能と同様に、Undo表領域 を利用して過去の状態を参照します。

  • 時刻(timestamp)または SCN(System Change Number) を指定することで、その時点の状態を再現できます。


🔧 Flashback Query の準備

  1. アーカイブログモードを有効化(未設定なら)

    • archive log list で確認

    • 有効化手順:

      • データベースを シャットダウン

      • MOUNT モードで起動

      • alter database archivelog; でアーカイブログモードに変更

      • データベースを再オープン

  2. Flashback機能の有効化

    • alter database flashback on; を実行


🧪 使用例(Monicaのケース)

  • 問題発生:12時、HRアプリ開発者が US_STATES テーブルの全データを誤って削除し、コミット。

  • 対応方法

    • Monicaは Flashback Query を使って削除前のデータを復元。

実験ステップ:

  1. US_STATES テーブルを作成し、データ挿入。

  2. 少し時間を置いてからデータを削除。

  3. SELECT * FROM US_STATES AS OF TIMESTAMP TO_TIMESTAMP('2025-07-09 06:15:00', 'YYYY-MM-DD HH24:MI:SS')
    を使用して、削除前の状態を参照。

  4. または AS OF SCN <SCN番号> を使って、特定の変更時点を指定。

  5. データ復元には INSERT INTO SELECT を使用可能。


🧠 SCN(System Change Number)とは?

  • Oracle 内部の「時計」のようなもので、トランザクションの整合性のある時点を識別

  • SELECT CURRENT_SCN FROM V$DATABASE で現在のSCNを取得。

  • TIMESTAMP_TO_SCN()SCN_TO_TIMESTAMP() 関数で変換可能。


💡 注意点

項目内容
使用条件アーカイブログモードが有効であること
データ復元INSERT INTO + Flashback Query が可能
Undo保持期間過去の時点情報は Undo に依存するため、保持設定が重要

✅ ローカル Undo 管理(Oracle Multi-Tenant 環境)


🏗 Undoの2つのモード(マルチテナント構成)

  • 共有(Shared)Undoモード
    CDBのrootに1つの共通Undo表領域のみを使用。

  • ローカル(Local)Undoモード(推奨):
    各PDBに1つのローカルUndo表領域を持つ。
    ※以下の操作時に必須

    • ホットクローン(稼働中クローン)

    • ダウンタイムほぼゼロでのPDB移動

    • PDBのリフレッシュやリストア

    • Proxy PDBの使用


⚙ Undoの管理方法(Automatic Undo Management)

  • undo_management パラメータが AUTO または NULL → 自動Undo管理が有効(デフォルト)

  • OracleがUndo表領域とUndoセグメントの管理を自動化。

  • Undo表領域は「自動エクステント管理されたローカル管理表領域」。


🗂 Undo表領域の確認・作成・切り替え

  • 確認方法

    • dba_tablespaces ビューで contents = 'UNDO' の行を確認

    • dba_data_files ビューで該当のファイルを確認

  • 新規作成例

    sql
    CREATE UNDO TABLESPACE undo_tbs2 DATAFILE '...' SIZE 100M;
  • 有効なUndo表領域の確認

    sql
    SHOW PARAMETER undo_tablespace;
  • 切り替え方法(undo_tbs2 を有効に)

    sql
    ALTER SYSTEM SET undo_tablespace = undo_tbs2;
  • 削除例(不要なUndo表領域)

    sql
    DROP TABLESPACE undo_tbs2 INCLUDING CONTENTS AND DATAFILES;

🔍 Undoの状態(v$undostat, dba_undo_extents

  • Undoセグメントの各エクステントのステータス:

    ステータス内容
    ACTIVE実行中トランザクションで使用中(上書き不可)
    UNEXPIREDコミット済だが保持期間内(可能なら保持)
    EXPIRED保持期間終了(上書き可能)
    v$undostat ビュー:過去のUndo使用状況を確認可能。

⏱ Undo保持期間(Undo Retention)

  • 初期設定UNDO_RETENTION = 900 秒(15分)

  • 保持期間は、最長のクエリ時間を少し超えるように自動調整される(自動拡張時)。

  • 設定変更例:

    sql
    ALTER SYSTEM SET undo_retention = 1800;
  • 注意点:

    • 保持期間を長くしすぎると、Undo表領域の空き不足で問題が起こる。

    • 空きが不足すると、UNEXPIREDなUndoも再利用されてしまい、エラー(ORA-01555: snapshot too old)の原因に。


🛡 Undo Retention Guarantee(保持保証)

  • 通常は、トランザクションを失敗させないために UNEXPIREDなUndoも上書きされる。

  • RETENTION GUARANTEE を指定することで、保持期間を強制的に保証できる。

    • 設定例:

      sql
      ALTER TABLESPACE undo_tbs1 RETENTION GUARANTEE;
    • 解除例:

      sql
      ALTER TABLESPACE undo_tbs1 RETENTION NOGUARANTEE;