• 更新前後のデータを比較・確認したい
  • 削除したデータをもう一度参照したい
  • 誤って削除してしまったデータを復旧したい
  • データベース全体ではなく、特定のデータのみ復旧したい

これらのお悩みは、Oracleのフラッシュバック機能(Flashback Technology)を使うことで解決できます。
今回は機能の1つ「Oracle Flashback Query」を実際に使用してみました。

データを誤って削除してしまうと焦りますよね。
落ち着いてフラッシュバック機能を使いましょう!

今回の執筆者は【Oracle 23ai 新機能】True Cacheインスタンスに接続してみましたを執筆しています!是非ご覧ください。

フラッシュバック機能とは?

フラッシュバック機能は、データベースの過去の状態を参照・復旧するための機能です。
その用途は大きく分類すると以下の2つとなります。

  1. 過去データの参照
    Oracle Databaseはトランザクションの変更前データをUNDO領域に保存しています。
    このUNDOデータを利用して、過去の特定時点のデータを参照可能です。
  2. データの復旧
    フラッシュバックログという高速リカバリ領域に保存された情報を使い、データベース全体や特定テーブルを過去の状態に戻すことができます。
    19c以降はフラッシュバックログが自動管理され、設定された保持期間を超えたログは自動削除されるようになりました。
    初期化パラメータDB_FLASHBACK_RETENTION_TARGET」で、フラッシュバックログの保持期間を指定することが可能です。

フラッシュバック機能を使う際は、参照・復旧したい過去時点のUNDOデータやフラッシュバックログが存在するか事前に確認しましょう。

Oracle Flashback Queryとは?

「Oracle Flashback Query」は、過去の特定時点のデータをSELECT文を用いて参照する機能です。
複雑な操作なしに、過去のデータを確認することができます。
先程ご紹介した用途の1.過去データの参照を担います。

以下の様に、SELECT文にAS OF句を付け、データを参照したい地点を指定します。

-- 時刻を指定(例:2025-08-27 11:53:59地点のデータを参照)
SELECT * FROM test_products AS OF TIMESTAMP TO_TIMESTAMP('2025-08-27 11:53:59', 'YYYY-MM-DD HH24:MI:SS');

-- 分数を指定(例:5分前のデータを参照)
SELECT * FROM test_products AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '5' MINUTE);

Oracle Flashback Queryを使用してみた

ここからは、Oracle Database 23ai環境で行った検証ログをもとに、Flashback Queryの使い方を順を追って説明します。

1. 環境接続

まずはOracle Databaseにsqlplusで接続し、作業対象のPDB(PDB1)に切り替えます。SYSTEMユーザーで操作を行います。

-- SYSTEMユーザで接続
SQL> show user
USER is "SYSTEM"

-- 作業対象のPDB(PDB1)に切り替え
SQL> alter session set container=PDB1;
Session altered.

SQL> show con_name

CON_NAME
------------------------------
PDB1

2. フラッシュバック関連パラメータの確認

UNDOデータとフラッシュバックログを確認し、フラッシュバック機能が使用可能であることを確認します。
今回はどちらもデフォルト値です。

-- フラッシュバック保持期間の確認(分単位、デフォルト1440分=24時間)
SQL> show parameter DB_FLASHBACK_RETENTION_TARGET;

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_flashback_retention_target	     integer	 1440


-- UNDO保持期間の確認(デフォルト900秒=15分)
SQL> show parameter UNDO_RETENTION;

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
undo_retention			     integer	 900

3. サンプルテーブルの作成と初期データ挿入

サンプルテーブル(test_products)を作成し、初期データ2件を挿入します。

-- フォーマット指定
SQL> set line 500
SQL> col product_name for a20
SQL> 
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

Session altered.

SQL> -- サンプルテーブルの作成
SQL> CREATE TABLE test_products (
  2      product_id NUMBER PRIMARY KEY,
  3      product_name VARCHAR2(100),
  4      updated_at DATE
  5  );

Table created.

SQL> -- 初期データの挿入
SQL> INSERT INTO test_products VALUES (1, 'Apple',SYSDATE);

1 row created.

SQL> INSERT INTO test_products VALUES (2, 'Orange',SYSDATE);

1 row created.

SQL> COMMIT;

Commit complete.

SQL> -- データの確認
SQL> select * from test_products;

PRODUCT_ID PRODUCT_NAME 	UPDATED_AT
---------- -------------------- -------------------
	 1 Apple		2025-08-27 11:53:40
	 2 Orange		2025-08-27 11:53:40

4. 過去のデータを参照(時刻指定)

データを更新後、AS OF句を使用して更新前のデータを参照します。

SQL> -- データの更新(OrangeをOrange_fixedに変更)
SQL> UPDATE test_products SET product_name = 'Orange_fixed', updated_at = SYSDATE WHERE product_id = 2;

1 row updated.

SQL> COMMIT;

Commit complete.

SQL> -- データの確認
SQL> select * from test_products;

PRODUCT_ID PRODUCT_NAME 	UPDATED_AT
---------- -------------------- -------------------
	 1 Apple		2025-08-27 11:53:40
	 2 Orange_fixed 	2025-08-27 11:54:20

SQL> -- 表作成時点を参照
SQL> SELECT * FROM test_products
  2  AS OF TIMESTAMP
  3  TO_TIMESTAMP('2025-08-27 11:53:40', 'YYYY-MM-DD HH24:MI:SS');

PRODUCT_ID PRODUCT_NAME 	UPDATED_AT
---------- -------------------- -------------------
	 1 Apple		2025-08-27 11:53:40
	 2 Orange		2025-08-27 11:53:40

AS OF句で時刻を指定することにより、データ更新前(PRODUCT_NAMEがOrangeのデータ)が取得できています。

5. 過去のデータを参照(分数指定)

分数を指定して過去データを参照する方法も検証します。

SQL> -- データの挿入
SQL> INSERT INTO test_products VALUES (3, 'Melon',SYSDATE);

1 row created.

SQL> -- データの確認
SQL> select * from test_products;

PRODUCT_ID PRODUCT_NAME 	UPDATED_AT
---------- -------------------- -------------------
	 1 Apple		2025-08-27 11:53:40
	 2 Orange_fixed 	2025-08-27 11:54:20
	 3 Melon		2025-08-27 11:57:40

SQL> -- 1分前のデータを参照(行挿入前)
SQL> SELECT * FROM test_products AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' MINUTE);

PRODUCT_ID PRODUCT_NAME 	UPDATED_AT
---------- -------------------- -------------------
	 1 Apple		2025-08-27 11:53:40
	 2 Orange_fixed 	2025-08-27 11:54:20

分数を指定することで、PRODUCT_NAMEがMelonのデータを挿入する前の状態を確認できています。

6.Flashback Queryの注意点

Oracle Flashback Queryでは、テーブル定義が変更された場合には、それ以前のデータを確認できません。
UNDO情報が保持されている場合でも同様です。
ALTER TABLE で列を追加・削除したり、テーブルの再作成を行ったりした場合には、Oracle Flashback Queryが使用できなくなる点には注意が必要です。

テーブル定義変更後にOracle Flashback Queryを実行すると、エラー(ORA-01466)が出力されます。

SQL> -- 列名変更
SQL> ALTER TABLE test_products RENAME COLUMN product_name TO product_fixed;

Table altered.

SQL> -- データの確認
SQL> select * from test_products;

PRODUCT_ID PRODUCT_FIXED		UPDATED_AT
---------- ----------------------------------------------------------

	 1 Apple			2025-08-27 11:53:40
	 2 Orange_fixed 		2025-08-27 11:54:20
	 3 Melon			2025-08-27 11:57:40


SQL> -- AS OF句を使用(エラーになる)
SQL> SELECT * FROM test_products AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' MINUTE);
SELECT * FROM test_products AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' MINUTE)
              *
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed
Help: https://docs.oracle.com/error-help/db/ora-01466/

おわりに

Oracle Flashback Queryは、過去の特定時点のデータを簡単に参照できる機能です。過去データの比較を行ったり、誤操作時の影響調査をしたりする際に有効です。

ただし、テーブル定義の変更を行う以前のデータは参照できない点は注意が必要です。
また、フラッシュバック機能を活用するには、保持期間の設定やUNDO領域の管理を適切に行う必要があります。

フラッシュバック機能には、Oracle Flashback Query以外にも便利な機能が沢山あります。
別の機会に紹介・検証させて頂く予定なので、そちらもよろしくお願いします。

当社ではOracle Databaseの最新機能を活用した検証や導入支援を行っております。
Oracleのフラッシュバック機能を使った効率的なデータ管理にご興味がある方は、ぜひお気軽にお問い合わせください。

フラッシュバック機能は様々な面で活躍します♪
もっと効率よくデータ管理がしたいという方は、ぜひこちらからお問い合わせください。

投稿者プロフィール

技術チーム
技術チーム
DBひとりでできるもんを盛り上げるべく、技術チームが立ち上がり早8年。ひとりでできるもんと言いつつ、技術者が読んでプッとなるような、極めてピンポイントでマニアックな技術ネタを執筆しています!
最新技術情報や資格情報をチェックしたいアナタ!毎日遊びに来てください。きっとお役に立てます。