【Oracle】Flashback Version Query・Flashback Transaction Query完全ガイド|VERSIONS BETWEEN で行レベルの変更履歴を追跡する方法まで解説

「昨日まで正しかったデータがいつ・誰によって変更されたのか」を調査したい場合、Oracle の Flashback Version Query が使えます。VERSIONS BETWEEN 句を使うと、特定の行(または条件に一致する行)が過去のどの時点でどのように変更されたかをSQL で一覧できます。

さらに Flashback Transaction QueryFLASHBACK_TRANSACTION_QUERY ビュー)と組み合わせると、特定のトランザクション(XID)の内容や UNDO SQL を確認できます。

この記事でわかること

  • Flashback Version Query(VERSIONS BETWEEN)で行の変更履歴を一覧する方法
  • VERSIONS_XID・VERSIONS_OPERATION・VERSIONS_STARTSCN などの擬似列の意味
  • SCN ベースと TIMESTAMP ベースの指定方法の違い
  • Flashback Transaction Query で XID からトランザクション詳細を確認する方法
  • UNDO_RETENTION と Flashback で参照できる履歴の期間
  • AS OF TIMESTAMP・Flashback Table との使い分け
スポンサーリンク

Flashback Version Query: VERSIONS BETWEEN の基本構文

VERSIONS BETWEEN を SELECT 文の FROM 句に付けることで、UNDO に残っている過去の各バージョン(コミット済みの変更点)を行として取得できます。

VERSIONS BETWEEN の基本的な使い方
-- VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE: 取得可能な全期間の変更履歴を返す
SELECT
    VERSIONS_XID          AS xid,                  -- トランザクション ID
    VERSIONS_OPERATION    AS operation,             -- I=INSERT, U=UPDATE, D=DELETE
    VERSIONS_STARTSCN     AS start_scn,             -- この版の開始 SCN
    VERSIONS_ENDSCN       AS end_scn,               -- この版の終了 SCN(NULL=現在の版)
    VERSIONS_STARTTIME    AS start_time,            -- この版の開始日時(近似)
    VERSIONS_ENDTIME      AS end_time,              -- この版の終了日時
    employee_id, last_name, salary                  -- テーブルの実データ
FROM   employees VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
WHERE  employee_id = 107
ORDER  BY VERSIONS_STARTSCN NULLS FIRST;

-- VERSIONS_OPERATION の値:
-- I: この版は INSERT によって作られた(行が新規追加された)
-- U: この版は UPDATE によって作られた(行が変更された)
-- D: この版は DELETE によって作られた(行が削除された)
-- NULL: 現在の版(最新データ)

-- TIMESTAMP ベースで過去2時間の変更履歴を取得する
SELECT
    VERSIONS_STARTTIME, VERSIONS_OPERATION, employee_id, last_name, salary
FROM   employees VERSIONS BETWEEN TIMESTAMP
         (SYSTIMESTAMP - INTERVAL '2' HOUR)
       AND
         SYSTIMESTAMP
WHERE  employee_id = 107
ORDER  BY VERSIONS_STARTTIME;

-- SCN ベースで特定の SCN 範囲を指定する
SELECT
    VERSIONS_STARTSCN, VERSIONS_OPERATION, employee_id, salary
FROM   employees VERSIONS BETWEEN SCN 5000000 AND 5100000
WHERE  department_id = 60
ORDER  BY VERSIONS_STARTSCN;
VERSIONS BETWEEN の動作の注意点

  • VERSIONS BETWEEN はコミット済みの変更だけを返す。ロールバックされたトランザクションは含まれない
  • 取得できる期間は UNDO_RETENTION の設定に依存する。UNDO が上書きされると古い版は取得不可になる
  • VERSIONS_STARTSCN が NULL の行は INSERT 前(行が存在しなかった期間)を示す場合がある
  • DDL(TRUNCATE・ALTER TABLE)が発生した場合は以前の版は取得できない

Flashback Version Query の擬似列一覧

擬似列 説明
VERSIONS_XID RAW(8) 変更を行ったトランザクション ID(XID)。FLASHBACK_TRANSACTION_QUERY の XID と一致する
VERSIONS_OPERATION VARCHAR2(1) 変更の種類:I(INSERT) / U(UPDATE) / D(DELETE)。現在の版は NULL
VERSIONS_STARTSCN NUMBER この版が開始した SCN。最初の版は NULL
VERSIONS_ENDSCN NUMBER この版が終了した SCN。現在の版(最新)は NULL
VERSIONS_STARTTIME VARCHAR2 この版が開始したおよその日時(SCN から変換した近似値)
VERSIONS_ENDTIME VARCHAR2 この版が終了したおよその日時。現在の版は NULL
VERSIONS_ROW_FILTER 行フィルタリングに使用する内部列(通常は使わない)

Flashback Transaction Query: XID からトランザクション詳細を確認する

Flashback Version Query で取得した VERSIONS_XID を使って、FLASHBACK_TRANSACTION_QUERY ビューからそのトランザクションが行ったすべての変更と UNDO SQL を取得できます。

Flashback Transaction Query で変更内容と UNDO SQL を確認する
-- FLASHBACK_TRANSACTION_QUERY の権限: SELECT ANY TRANSACTION または FLASHBACK ANY TABLE が必要

-- XID を指定してそのトランザクションの詳細を確認する
SELECT
    xid,
    operation,          -- INSERT / UPDATE / DELETE / UNKNOWN
    start_timestamp,    -- トランザクション開始日時
    commit_timestamp,   -- COMMIT 日時
    logon_user,         -- 変更を行ったユーザー
    undo_sql,           -- 変更を元に戻すための SQL(UNDO SQL)
    table_name,
    table_owner
FROM   FLASHBACK_TRANSACTION_QUERY
WHERE  xid = HEXTORAW('01000A0058060000')  -- VERSIONS_XID の値
ORDER  BY undo_change#;

-- VERSIONS BETWEEN と FLASHBACK_TRANSACTION_QUERY を結合して確認する
SELECT
    v.VERSIONS_STARTTIME,
    v.VERSIONS_OPERATION,
    v.employee_id,
    v.last_name,
    v.salary,
    f.logon_user,        -- 変更を行ったユーザー
    f.undo_sql           -- 変更を元に戻す SQL
FROM   employees VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE v
JOIN   FLASHBACK_TRANSACTION_QUERY f ON v.VERSIONS_XID = f.xid
WHERE  v.employee_id = 107
  AND  v.VERSIONS_OPERATION IS NOT NULL    -- 現在の版を除く
ORDER  BY v.VERSIONS_STARTSCN;

-- UNDO SQL を使って特定の変更を手動で元に戻す例
-- undo_sql: 'UPDATE "HR"."EMPLOYEES" SET SALARY=5000 WHERE ROWID=''AAABkUAAEAAAAC7AAA'';'
-- → undo_sql を実行すれば変更前の状態に戻せる

Flashback Version Query と AS OF TIMESTAMP の使い分け

機能 目的 取得対象 主な用途
AS OF TIMESTAMP 過去の特定時点のスナップショット その時点での行の値(1行1版) 「昨日の午前9時のデータを見たい」
VERSIONS BETWEEN 行の変更履歴の一覧 期間内のすべての版(複数行) 「この行は誰が・いつ・何回変更したか」
Flashback Table テーブルを過去の状態に戻す(DML) テーブル全体を過去に戻す 「誤って DELETE したテーブルを元に戻したい」
Flashback Transaction Query 特定トランザクションの詳細と UNDO SQL トランザクションが変更した全行と操作 「このトランザクションが何を変更したか・元に戻したい」

UNDO_RETENTION と取得できる履歴の期間

UNDO_RETENTION と参照可能期間の確認
-- 現在の UNDO_RETENTION を確認する(秒単位)
SHOW PARAMETER undo_retention;
-- undo_retention = 900 (デフォルト): 最低 900秒(15分)UNDO を保持する保証

-- より長い履歴を参照するには UNDO_RETENTION を増やす
ALTER SYSTEM SET UNDO_RETENTION = 86400;  -- 24時間(86400秒)保持

-- undo_retention はガイドラインであり、UNDO 表領域が満杯の場合は
-- 古い UNDO から上書きされる(GUARANTEE なし)
-- UNDO 表領域に RETENTION GUARANTEE を設定すると期限前上書きを防止できる
ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;

-- 現在参照可能な SCN の範囲を確認する
SELECT oldest_flashback_scn, oldest_flashback_time
FROM   V$FLASHBACK_DATABASE_LOG;
-- oldest_flashback_scn より前の SCN は参照できない(UNDO が消えている可能性)

-- ORA-01555 (snapshot too old) が出たら UNDO が不足している
-- VERSIONS BETWEEN で ORA-01555 が出る場合は UNDO_RETENTION を増やすか
-- UNDO 表領域を拡張する

まとめ

  • Flashback Version Query:SELECT 文に VERSIONS BETWEEN SCN/TIMESTAMP を付けるだけで行の変更履歴を取得できる。コミット済みの変更がすべて列挙される
  • 擬似列:VERSIONS_XID(トランザクション ID)・VERSIONS_OPERATION(I/U/D)・VERSIONS_STARTSCN / ENDSCN・VERSIONS_STARTTIME / ENDTIME が取得できる
  • Flashback Transaction Query:FLASHBACK_TRANSACTION_QUERY ビューで XID から「誰が・いつ・何を変更したか」と UNDO SQL を確認できる。SELECT ANY TRANSACTION 権限が必要
  • UNDO_RETENTION:参照できる履歴の期間を制御する。デフォルト 900 秒を超えると UNDO が上書きされる可能性がある
  • AS OF TIMESTAMP との違い:AS OF は特定時点の単一スナップショット、VERSIONS BETWEEN は期間内の全変更履歴を返す

行レベルの変更を長期保存する場合は Flashback Data Archive(Total Recall)も有効です。Flashback Data Archive 完全ガイドを参照してください。Flashback Table でテーブル全体を過去の状態に戻す方法は Flashback 完全ガイドも参照してください。