マニュアルの例はあまり面白くないので、 OBE (Oracle By Example) に沿って練習してみました。
表領域を作ります。
#pre{{ SQL> CREATE SMALLFILE TABLESPACE fla_tbs1
2 DATAFILE '/u02/oradata/orcl/fla_tbs01.dbf' 3 SIZE 10M REUSE AUTOEXTEND ON 4 NOLOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO 5 /
表領域が作成されました。 }}
hrユーザのロックを解除します。 DBCA から DB を作ったときにサンプルスキーマを入れるというようにしていない場合は、 別途インストールするかDBを作り直しましょう。
パスワードは簡単なものは蹴られてしまうように設定してしまったので、 ちょっと長くなっています。
#pre{{ SQL> ALTER USER hr identified by hrhrhrhr0 ACCOUNT UNLOCK
2 /
ユーザーが変更されました。 }}
hr にフラッシュバック・アーカイブの権限を付与します。
#pre{{ SQL> GRANT FLASHBACK ARCHIVE ADMINISTER TO hr
2 /
権限付与が成功しました。 }}
hrユーザでつなぎます。
#pre{{ SQL> conn hr/hrhrhrhr0@orcl 接続されました。 }}
フラッシュバック・アーカイブを作成します。
#pre{{ SQL> CREATE FLASHBACK ARCHIVE fla1
2 TABLESPACE fla_tbs1 3 QUOTA 10M 4 RETENTION 1 YEAR 5 /
フラッシュバック・アーカイブが作成されました。 }}
hr.employees 表にフラッシュバック・アーカイブを設定します。 この表の変更履歴が追えるようになる、ということですね。
#pre{{ SQL> ALTER TABLE hr.employees FLASHBACK ARCHIVE fla1
2 /
表が変更されました。 }}
Foxさんの給与を表示してみます。
#pre{{ SQL> col employee_id format 999999999 SQL> col last_name format a20 SQL> col salary format 9999999999 SQL> SELECT employee_id, last_name, salary
2 FROM hr.employees 3 WHERE last_name = 'Fox' 4 /
EMPLOYEE_ID LAST_NAME SALARY
170 Fox 9600
}}
給与を1000ドルずつ3回増やしてみるそうです。
#pre{{ SQL> UPDATE hr.employees
2 SET salary = salary + 1000 3 WHERE last_name = 'Fox' 4 /
1行が更新されました。
SQL> COMMIT
2 /
コミットが完了しました。
SQL> UPDATE hr.employees
2 SET salary = salary + 1000 3 WHERE last_name = 'Fox' 4 /
1行が更新されました。
SQL> COMMIT
2 /
コミットが完了しました。 SQL> UPDATE hr.employees
2 SET salary = salary + 1000 3 WHERE last_name = 'Fox' 4 /
1行が更新されました。
SQL> COMMIT
2 /
コミットが完了しました。
}}
3000ドル増えてます。
#pre{{ SQL> SELECT employee_id, last_name, salary
2 FROM hr.employees 3 WHERE last_name = 'Fox' 4 /
EMPLOYEE_ID LAST_NAME SALARY
170 Fox 12600
}}
フラッシュバック・データ・アーカイブのおかげで、 ちょっと前の状態を取得できたりします。
#pre{{ SQL> SELECT employee_id, last_name, salary
2 FROM hr.employees 3 AS OF TIMESTAMP 4 (SYSTIMESTAMP - INTERVAL '2' MINUTE) 5 WHERE last_name = 'Fox' 6 /
EMPLOYEE_ID LAST_NAME SALARY
170 Fox 11600
SQL> SQL> l4
4* (SYSTIMESTAMP - INTERVAL '2' MINUTE)
SQL> c /'2'/'4'/
4* (SYSTIMESTAMP - INTERVAL '4' MINUTE)
SQL> l
1 SELECT employee_id, last_name, salary 2 FROM hr.employees 3 AS OF TIMESTAMP 4 (SYSTIMESTAMP - INTERVAL '4' MINUTE) 5* WHERE last_name = 'Fox'
SQL> r
1 SELECT employee_id, last_name, salary 2 FROM hr.employees 3 AS OF TIMESTAMP 4 (SYSTIMESTAMP - INTERVAL '4' MINUTE) 5* WHERE last_name = 'Fox'
EMPLOYEE_ID LAST_NAME SALARY
170 Fox 9600
SQL> }}
このあたりを実行計画から調べることもできます。
#pre{{ SQL> explain plan for
2 SELECT employee_id, last_name, salary 3 FROM hr.employees 4 AS OF TIMESTAMP 5 (SYSTIMESTAMP - INTERVAL '5' MINUTE) 6 WHERE last_name = 'Fox' 7 /
解析されました。
SQL> @?/rdbms/admin/utlxpls
PLAN_TABLE_OUTPUT
Plan hash value: 1836971204
Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time | Pstart | Pstop |
0 | SELECT STATEMENT | 2 | 80 | 9 (12) | 00:00:01 | |||
1 | VIEW | 2 | 80 | 9 (12) | 00:00:01 | |||
2 | UNION-ALL | |||||||
* 3 | FILTER | |||||||
4 | PARTITION RANGE SINGLE | 1 | 66 | 3 (0) | 00:00:01 | KEY | 1 | |
* 5 | TABLE ACCESS FULL | SYS_FBA_HIST_73953 | 1 | 66 | 3 (0) | 00:00:01 | KEY | 1 |
* 6 | FILTER | |||||||
* 7 | HASH JOIN OUTER | 1 | 2056 | 6 (17) | 00:00:01 | |||
* 8 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 28 | 2 (0) | 00:00:01 | ||
* 9 | INDEX RANGE SCAN | EMP_NAME_IX | 1 | 1 (0) | 00:00:01 | |||
* 10 | TABLE ACCESS FULL | SYS_FBA_TCRV_73953 | 1 | 2028 | 3 (0) | 00:00:01 |
Predicate Information (identified by operation id):
3 - filter("TIMESTAMP_TO_SCN"(SYSTIMESTAMP(6)-INTERVAL'+00 00:05:00' DAY(2) TO SECOND(0))<1572805) 5 - filter("LAST_NAME"='Fox' AND "ENDSCN"<=1572805 AND "ENDSCN">"TIMESTAMP_TO_SCN"(SYSTIMESTAMP(6)-INTERVAL'+00 00:05:00' DAY(2) TO SECOND(0)) AND ("STARTSCN" IS NULL OR "STARTSCN"<="TIMESTAMP_TO_SCN"(SYSTIMESTAMP(6)-INTERVAL'+00 00:05:00' DAY(2) TO SECOND(0)))) 6 - filter("STARTSCN"<="TIMESTAMP_TO_SCN"(SYSTIMESTAMP(6)-INTERVAL'+00 00:05:00' DAY(2) TO SECOND(0)) OR "STARTSCN" IS NULL) 7 - access("T".ROWID=CHARTOROWID("RID"(+))) 8 - filter("T"."VERSIONS_STARTSCN" IS NULL) 9 - access("T"."LAST_NAME"='Fox') 10 - filter(("ENDSCN"(+) IS NULL OR "ENDSCN"(+)>1572805) AND ("STARTSCN"(+) IS NULL OR "STARTSCN"(+)<1572805))
Note
- dynamic sampling used for this statement (level=2)
36行が選択されました。 }}
最後の例は、前の値に戻せますよというものでした。
#pre{{ SQL> UPDATE hr.employees
2 SET salary = 3 (SELECT salary FROM hr.employees 4 AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE) 5 WHERE last_name = 'Fox') 6 WHERE last_name = 'Fox' 7 /
1行が更新されました。
SQL> COMMIT
2 /
コミットが完了しました。
SQL> SELECT salary FROM hr.employees
2 WHERE last_name = 'Fox' 3 /
SALARY
10600
}}
どのへんを見ればいいかというところです。
まずはどの表を見ればいいのかを調べてみます。
#pre{{ SQL> SELECT table_name FROM dict
2 WHERE table_name LIKE '%FLASHBACK_ARCHIVE%' 3 /
TABLE_NAME
DBA_FLASHBACK_ARCHIVE DBA_FLASHBACK_ARCHIVE_TABLES DBA_FLASHBACK_ARCHIVE_TS USER_FLASHBACK_ARCHIVE USER_FLASHBACK_ARCHIVE_TABLES
}}
dba_flashback_archive表です。いつ作ったかですね。
#pre{{ SQL> SELECT flashback_archive_name, create_time, status
2 FROM dba_flashback_archive 3 /
FLASHBACK_ARCHIVE_NAME
CREATE_TIME
STATUS
FLA1 09-09-20 17:31:36.000000000
}}
dba_flashback_archive_ts表では表領域がわかります。
#pre{{ SQL> SELECT * FROM dba_flashback_archive_ts
2 /
FLASHBACK_ARCHIVE_NAME
FLASHBACK_ARCHIVE#
TABLESPACE_NAME
QUOTA_IN_MB
FLA1
1
FLA_TBS1 10
SQL> }}
dba_flashback_archive_table表では表の情報が取れます。
#pre{{ SQL> col table_name format a10 SQL> col owner_name format a10 SQL> col flashback_archive_name format a10 SQL> col archive_table_name format a20 SQL> SELECT * FROM dba_flashback_archive_tables
2 /
TABLE_NAME OWNER_NAME FLASHBACK_ ARCHIVE_TABLE_NAME STATUS
EMPLOYEES HR FLA1 SYS_FBA_HIST_73953 ENABLED
}}
放っておけば設定した期間で消えますが、 明示的に古い履歴を消すということもできます。
#pre{{ [oracle@ora1 flada]$ sqlplus hr/hrhrhrhr0@orcl ... SQL> ALTER FLASHBACK ARCHIVE fla1
2 PURGE BEFORE TIMESTAMP 3 (SYSTIMESTAMP - INTERVAL '10' MINUTE) 4 /
フラッシュバック・アーカイブが変更されました。
SQL> }}
このアーカイブ領域を増やすこともできます。
追加で表領域を作ります。
#pre{{ SQL> conn sys/oracle@orcl as sysdba 接続されました。 SQL> CREATE SMALLFILE TABLESPACE fla_tbs2
2 DATAFILE '/u02/oradata/orcl/fla_tbs2.dbf' 3 SIZE 10M REUSE AUTOEXTEND ON 4 NOLOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO 5 /
表領域が作成されました。 }}
hr ユーザで増やしてみます。
#pre{{ SQL> connect hr/hrhrhrhr0 接続されました。 SQL> ALTER FLASHBACK ARCHIVE fla1
2 ADD TABLESPACE fla_tbs2 3 QUOTA 5M 4 /
フラッシュバック・アーカイブが変更されました。
SQL> ALTER FLASHBACK ARCHIVE fla1
2 MODIFY RETENTION 2 YEAR 3 /
フラッシュバック・アーカイブが変更されました。 }}
保持期間を変えることもできます。
#pre{{ SQL> ALTER FLASHBACK ARCHIVE fla1
2 MODIFY RETENTION 2 YEAR 3 /
フラッシュバック・アーカイブが変更されました。 }}
フラッシュバック・アーカイブを無効にもできます。
#pre{{ SQL> ALTER TABLE hr.employees NO FLASHBACK ARCHIVE
2 /
表が変更されました。 }}
削除は DROP です。
#pre{{ SQL> DROP FLASHBACK ARCHIVE fla1
2 /
フラッシュバック・アーカイブが削除されました。 }}
練習のために使った表領域などは消しておきます。
#pre{{ SQL> conn sys/oracle@orcl as sysdba 接続されました。 SQL> DROP TABLESPACE fla_tbs1 INCLUDING CONTENTS
2 /
表領域が削除されました。
SQL> DROP TABLESPACE fla_tbs2 INCLUDING CONTENTS
2 /
表領域が削除されました。
SQL> !ls /u02/oradata/orcl/ control01.ctl fla_tbs01.dbf redo03.log sbyredo04.log undotbs01.dbf control02.ctl fla_tbs2.dbf sbyredo01.log sysaux01.dbf users01.dbf encrypt01.dbf redo01.log sbyredo02.log system01.dbf example01.dbf redo02.log sbyredo03.log temp01.dbf
SQL> !rm /u02/oradata/orcl/fla_*.dbf }}