■建立FBDA所在的表空间likingfbda CREATE TABLESPACE likingfbda DATAFILE SIZE 50M AUTOEXTEND ON NEXT 10M MAXSIZE 1G; ■在表空间上建立FBDA,retention为1个月 CREATE FLASHBACK ARCHIVE likingfbda TABLESPACE likingfbda RETENTION 1 MONTH; ■设置默认FBDA ALTER FLASHBACK ARCHIVE likingfbda SET DEFAULT; col flashback_archive_name for a30 SELECT flashback_archive_name,status FROM dba_flashback_archive; FLASHBACK_ARCHIVE_NAME STATUS ------------------------------ -------- LIKINGFBDA DEFAULT ■建立一个小的undo tablespace用于测试 SYS@prod1> show parameter undo NAME TYPE VALUE ------------------------ ----------- ------------ undo_management string AUTO undo_retention integer 900 undo_tablespace string UNDOTBS1 CREATE UNDO TABLESPACE likingundotbs DATAFILE SIZE 4m; ALTER SYSTEM SET UNDO_TABLESPACE=likingundotbs; SYS@prod1> show parameter undo NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ undo_management string AUTO undo_retention integer 900 undo_tablespace string LIKINGUNDOTBS ■授权用户scott可以使用flashback archive GRANT FLASHBACK ARCHIVE ON likingfbda TO scott; ■设置table启用flashback archive SYS@prod1> conn scott/tiger SCOTT@prod1> CREATE TABLE emp1 AS SELECT * FROM emp; SCOTT@prod1> ALTER TABLE emp1 FLASHBACK ARCHIVE;
以下继续:
■建立测试环境(查询闪回归档可以基于scn或timestamp) SYS@prod1> select current_scn from v$database; CURRENT_SCN --------------- 1602437 SCOTT@prod1> select count(*) from emp1; COUNT(*) --------------- 14 SCOTT@prod1> delete from emp1 where EMPNO<7788; 7 rows deleted. SCOTT@prod1> commit; 循环脚本,覆盖undo block: SCOTT@prod1> create table emp2 as select * from emp; begin for i in 1..1000 loop insert into emp2 select * from emp; commit; end loop; end; / PL/SQL procedure successfully completed. SCOTT@prod1> set autotrace on SCOTT@prod1> select count(*) from emp1 as of scn 1602437; COUNT(*) --------------- 14 Execution Plan ---------------------------------------------------------- Plan hash value: 3317502069 ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 23 (9)| 00:00:01 | | | | 1 | SORT AGGREGATE | | 1 | | | | | | | 2 | VIEW | | 8 | | 23 (9)| 00:00:01 | | | | 3 | UNION-ALL | | | | | | | | | 4 | PARTITION RANGE SINGLE| | 7 | 196 | 14 (0)| 00:00:01 | 1 | 1 | |* 5 | TABLE ACCESS FULL | SYS_FBA_HIST_88967 | 7 | 196 | 14 (0)| 00:00:01 | 1 | 1 | |* 6 | FILTER | | | | | | | | | 7 | MERGE JOIN OUTER | | 1 | 2040 | 9 (23)| 00:00:01 | | | | 8 | SORT JOIN | | 1 | 12 | 6 (17)| 00:00:01 | | | |* 9 | TABLE ACCESS FULL | EMP1 | 1 | 12 | 5 (0)| 00:00:01 | | | |* 10 | SORT JOIN | | 1 | 2028 | 3 (34)| 00:00:01 | | | |* 11 | TABLE ACCESS FULL | SYS_FBA_TCRV_88967 | 1 | 2028 | 2 (0)| 00:00:01 | | | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - filter("ENDSCN">1602437 AND "ENDSCN"<=1605534 AND ("STARTSCN" IS NULL OR "STARTSCN"<=1602437) AND ("OPERATION" IS NULL OR "OPERATION"<>'D')) 6 - filter("STARTSCN"<=1602437 OR "STARTSCN" IS NULL) 9 - filter(("T"."VERSIONS_STARTSCN" IS NULL OR "T"."VERSIONS_STARTSCN"<=1602437) AND ("T"."VERSIONS_ENDSCN" IS NULL OR "T"."VERSIONS_ENDSCN">1602437) AND ("T"."VERSIONS_OPERATION" IS NULL OR "T"."VERSIONS_OPERATION"<>'D')) 10 - access("RID"(+)=ROWIDTOCHAR("T".ROWID)) filter("RID"(+)=ROWIDTOCHAR("T".ROWID)) 11 - filter(("ENDSCN"(+) IS NULL OR "ENDSCN"(+)>1605534) AND ("STARTSCN"(+) IS NULL OR "STARTSCN"(+)<1605534)) Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 28 recursive calls 0 db block gets 76 consistent gets 0 physical reads 0 redo size 526 bytes sent via SQL*Net to client 519 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 3 sorts (memory) 0 sorts (disk) 1 rows processed 通过查询的执行计划可以看到,数据是从SYS_FBA_TCRV_88967(闪回区)读出,可以证明此历史数据不是从undo block而是flashback archive读出。
继续:
■最值得验证的时刻来了,多次修改员工7788的工资数,看看历史变化情况! SELECT versions_xid, versions_startscn, versions_endscn, empno, sal FROM emp1 versions BETWEEN TIMESTAMP(systimestamp - INTERVAL '15' minute) AND maxvalue WHERE empno = 7788 ORDER BY 2 NULLS FIRST; UPDATE emp1 SET sal = 40000 WHERE empno = 7788; commit; UPDATE emp1 SET sal = 50000 WHERE empno = 7788; commit; UPDATE emp1 SET sal = 60000 WHERE empno = 7788; commit; UPDATE emp1 SET sal = 45000 WHERE empno = 7788; commit; VERSIONS_XID VERSIONS_STARTSCN VERSIONS_ENDSCN EMPNO SAL ---------------- ----------------- --------------- --------------- --------------- 1606144 7788 3000 1900110006000000 1606144 1606150 7788 4000 1B00060007000000 1606150 1606153 7788 5000 18001C0006000000 1606153 1606156 7788 6000 1700170006000000 1606156 7788 4500 SCOTT@prod1> select scn_to_timestamp(1606150) scn from dual; SCN -------------------------------------- 01-MAR-18 04.41.04.000000000 PM SELECT to_char(scn_to_timestamp(1606150), 'yyyy-mm-dd hh24:mi:ss') chr, timestamp_to_scn(scn_to_timestamp(1606150)) dt FROM dual; CHR DT ------------------- --------------- 2018-03-01 16:41:04 1606148 select timestamp_to_scn(sysdate-1) scn from dual; 将scn显示为时间 col start_time for a35 col end_time for a35 SELECT to_char(scn_to_timestamp(nvl(versions_startscn, timestamp_to_scn(SYSDATE - 1))), 'yyyy-mm-dd hh24:mi:ss') start_time, to_char(scn_to_timestamp(nvl(versions_endscn, timestamp_to_scn(SYSDATE))), 'yyyy-mm-dd hh24:mi:ss') end_time, empno, sal FROM emp1 versions BETWEEN TIMESTAMP(systimestamp - INTERVAL '5' DAY) AND maxvalue WHERE empno = 7788 ORDER BY 2,1 NULLS FIRST; START_TIME END_TIME EMPNO SAL ------------------- ------------------- ---- ----- 2016-02-03 10:28:54 2018-03-01 16:40:52 7788 3000 2018-03-01 16:40:52 2018-03-01 16:41:04 7788 4000 2018-03-01 16:41:04 2018-03-01 16:41:04 7788 5000 2018-03-01 16:41:04 2018-03-01 16:41:04 7788 6000 2018-03-01 16:41:04 2018-03-01 17:31:20 7788 4500 2018-03-01 17:31:20 2018-03-01 17:31:35 7788 40000 2018-03-01 17:31:35 2018-03-01 17:31:41 7788 50000 2018-03-01 17:31:41 2018-03-01 17:31:53 7788 60000 2018-03-01 17:31:53 2018-03-01 17:32:08 7788 45000
以上可以清晰的看到某个时间段员工7788的工资数是多少!
所以如果设置关键表的FBDA为合适的保留策略,并加以适当的维护,这个数据履历的功能就完美实现了。
文章评论