Oracle フラッシュバック機能検証

### はじめに
Oracleのフラッシュバック機能は、データベースの状態を過去の時点に戻すことができる機能です。QiitaにはRMANによる復旧方法に関する記事がいくつかありますが、フラッシュバック機能についての記載が少なかったため、この記事ではその内容について紹介します。

#### フラッシュバックとRMANの違いとユースケース
 - フラッシュバック
   - ユースケース: 誤ったデータ操作やシステム変更後の迅速なロールバックができる。フラッシュバックを使用して元の状態に戻し、繰り返しテストを行うことができる
   - 制限: 物理的に削除されたデータファイルを復元できない。例えば、管理者が誤ってrmコマンドでデータファイルを削除してしまった場合など
 - RMAN（Recovery Manager）
   - ユースケース: 物理的なデータファイルの削除や破損が発生した場合、またはハードウェア障害への対応
   - 制限: バックアップの管理が必要で、リストアには時間がかかる(場合がある)

フラッシュバック機能とRMANの詳細については、以下のOracleのガイドを参照してください

https://docs.oracle.com/cd/F19136_01/bradv/using-flasback-database-restore-points.html#GUID-909BBEEF-389B-443B-8CD7-F3C027AAFFF3


### 事前準備
フラッシュバック機能を使用するには、以下の3つの設定が必要です。

 - 高速リカバリ領域の構成
 - REDOログ・ファイルのアーカイブの有効化
 - データベース全体のフラッシュバック・データベース機能を有効化

詳しい手順は、以下のリンクを参照してください。

https://docs.oracle.com/cd/E57425_01/121/ADMQS/GUID-2598AA28-DBBB-4B40-AABC-B28FB5C5F4BE.htm

**高速リカバリ領域の構成**
以下の手順で高速リカバリ領域を設定します。

高速リカバリ領域の設定と割り当て
①OS上にリカバリ領域を作成。
```
mkdir -p /u01/app/oracle/flash_recovery_area
chown oracle:oinstall /u01/app/oracle/flash_recovery_area
chmod 755 /u01/app/oracle/flash_recovery_area
```
②Oracle側で割り当て
```sql
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST = '/u01/app/oracle/flash_recovery_area' SCOPE=BOTH;
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 20G SCOPE=BOTH;
```
設定後の確認
```sql
SHOW PARAMETER db_recovery_file_dest;
```
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/505505a9-be4d-933c-4c1a-1f9a60311a5b.png)


**REDOログ・ファイルのアーカイブの有効化**
LOG_MODEがNOARCHIVELOGの場合、以下のコマンドでアーカイブモードを有効にします。

```sql
SELECT LOG_MODE FROM V$DATABASE;
ALTER DATABASE ARCHIVELOG;
```
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/a497747f-0107-c2bc-8702-cf9812353352.png)


**データベース全体のフラッシュバック・データベース機能を有効化**
FLASHBACK_ONがNOの場合、以下のコマンドで有効化します。

```sql
SELECT FLASHBACK_ON FROM V$DATABASE;
ALTER DATABASE FLASHBACK ON;
```

![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/e0132726-df2d-6860-da94-e6a0177fd55d.png)


注意点
SYSユーザーが所有するオブジェクトはリサイクルビンに入らないという制約があります。そのため、SYSユーザーで削除したオブジェクトはリサイクルビンに表示されません。私は、横着してSYSユーザーで作業していてリサイクルビンに何も表示されず「？？？」になりました。このため、以下のように新しいユーザーを作成しました。

sql
```sql
CREATE USER akichang IDENTIFIED BY password;
GRANT CONNECT, RESOURCE TO akichang;
ALTER USER akichang QUOTA UNLIMITED ON USERS;
GRANT SELECT_CATALOG_ROLE TO akichang;
GRANT SELECT ANY DICTIONARY TO akichang;
```

## 検証
①テーブルの作成
フラッシュバック・テーブル: テーブル全体を過去の状態に戻す操作。
フラッシュバック・ドロップ: 誤って削除したテーブルをリサイクルビンから復元。

### テーブルの作成とデータの操作
フラッシュバック・テーブルを利用して、データの更新の前後での状態を確認するために以下のテーブルを作成します。目的としては、1つのテーブルでデータの更新の前後での戻しができるように、INSERTとUPDATEを実行したテーブルを作成します。
```sql
CREATE TABLE eiyou (
    id NUMBER PRIMARY KEY,
    name VARCHAR2(50)
);

INSERT INTO eiyou (id, name) VALUES (1, 'Purin');
INSERT INTO eiyou (id, name) VALUES (2, 'Pudding');
UPDATE eiyou SET name = 'UpdatedPurin' WHERE id = 1;
```
### フラッシュバック・テーブル: テーブル全体を過去の状態に戻す操作

SCNを使用してテーブルを過去の状態に戻します（特定の時刻でも可能です）。SCN（System Change Number）は、Oracleデータベースでトランザクションに紐づく一意の番号です。

以下のコマンドでSCNの番号を確認します。
```sql
SELECT VERSIONS_STARTSCN, VERSIONS_ENDSCN,id, name
FROM eiyou VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
```
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/9ef4ebdb-4397-25c2-9bc9-28b95ec3f0b8.png)

表示された、SCNから復元を行います。そのSCNから復元を行うことで、UpdatedPurinからPurinに復元できます。以下はそのキャプチャです。
```sql
FLASHBACK TABLE eiyou TO SCN 4056898;
SELECT * FROM eiyou;
```
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/a3da4fef-1371-f64c-cbab-76235df3fbb6.png)

また、別のSCNから復元を行うことで、Purinに復元できたことも確認しました。以下はそのキャプチャです。
```sql
FLASHBACK TABLE eiyou TO SCN 4056651;
SELECT * FROM eiyou;
```
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/3546c45b-3145-6160-c252-8397437dafa0.png)


#### フラッシュバック・ドロップ: 誤って削除したテーブルをリサイクルビンから復元
Drop tableを実行した後に RECYCLEBINを確認します。
```sql
DROP table eiyou;
SHOW RECYCLEBIN;
```
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/54249155-cf35-f658-6de2-574f45d60631.png)

EIYOUがあることが確認できたので、BEFORE DROPを使うことで、DROPされたTableが戻ったことを確認しました。以下はそのキャプチャです。
```sql
FLASHBACK TABLE eiyou TO BEFORE DROP;
SELECT * FROM eiyou;
```

![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322881/78cf4e20-cee3-80d6-eed9-b35713650b37.png)

### まとめ
Oracleのフラッシュバック機能はRMANと比較した場合に、素早く復元できますし、事前にバックアップを明示的に取得したりしなくてよいので、開発や検証の際に非常に便利そうです。