Oracle 10g 閃回查詢特性的增強:
Oracle 9i提供了閃回特性增強,爲數據恢復帶來了極大的方便,但是Oracle 9i的閃回查詢只能提供某個時間點的數據視圖,並不能告訴用戶這樣的數據經過了幾個事務、怎樣的修改(UPDATE、INSERT、DELETE等),而這些信息在回滾段中是存在的,在Oracle 10g中,Oracle進一步加強了閃回查詢的特性,提供了以下兩種閃回查詢:
·閃回版本查詢(Flashback Versions Query);
·閃回事務查詢(Flashback Transaction Query)。
閃回版本查詢允許使用一個新的VERSIONS子句查詢兩個時間點或者SCN之間的數據版本。這些版本可以按照事務進行區分,閃回版本查詢只返回提交數據,未提交數據不被顯示。
通過以下示例,來理解閃回版本查詢的信用。首先創建一個測試表,執行一系列的DML操作:
tq@TQGZS> create table t as select username,user_id from dba_users;
Table created.
tq@TQGZS> select * from t;USERNAME USER_ID
------------------------------ ----------
TQ 76
RMAN 71
T2 69
PERFSTAT 62
TEST 66
HR 55
OE 56
DIP 19
SH 58
IX 57
MDDATA 50
PM 59
T4 72
BI 60
T5 73
SQLLDR 75
T1 68
T6 74
TSMSYS 21
T3 70
SCOTT 54
OLAPSYS 47
SI_INFORMTN_SCHEMA 45
ORDPLUGINS 44
XDB 38
SYSMAN 51
ANONYMOUS 39
CTXSYS 36
WMSYS 25
DBSNMP 24
DMSYS 35
EXFSYS 34
ORDSYS 43
MDSYS 46
SYSTEM 5
SYS 0
MGMT_VIEW 53
CSMIG 64
OUTLN 11
39 rows selected.
tq@TQGZS> delete from t where username='OUTLN';
1 row deleted.
tq@TQGZS> commit;
Commit complete.
tq@TQGZS> delete from t where username='TEST';
1 row deleted.
tq@TQGZS> commit;
Commit complete.
tq@TQGZS> update t set user_id = 6 where username = 'TQ';
1 row updated.
tq@TQGZS> commit;
Commit complete.
tq@TQGZS> delete from t where user_id > 10;
34 rows deleted.
tq@TQGZS> commit;
Commit complete.
tq@TQGZS> select * from t;
USERNAME USER_ID
-------------------- ----------
TQ 6
SYSTEM 5
SYS 0
tq@TQGZS> insert into t values('DBTAN',8);
1 row created.
tq@TQGZS> commit;
Commit complete.
至此數據庫中已經交替執行了多個事務,進行了衆多的數據修改,現在的測試表已經與最初完全不同了。如果使用Oracle 9i的閃回查詢,是很難區分這些不同事務的變更,找到合適的、正確的數據將變得極爲困難。
再了看看Oracle 10g的閃回版本查詢,通過vertions子句和對數據表引入了系列的僞列(versions_starttime等),可以獲得對數據表的所有事務操作,注意以下輸出中versions_operation代表了不同類型的操作(D-Delete、I-Insert、U-Update),VERSIONS_XID是一個重要數據,代表了不同版本的事務ID:
tq@TQGZS> select versions_starttime,versions_endtime,versions_xid,
2 versions_operation,username,user_id
3 from t versions between timestamp minvalue and maxvalue;VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_XID V USERNAME USER_ID
------------------------- ------------------------- ---------------- - -------------------- -------
04-JAN-10 11.28.50 AM 0300280024190000 D CSMIG 64
04-JAN-10 11.28.50 AM 0300280024190000 D MGMT_VIEW 53
04-JAN-10 11.28.50 AM 0300280024190000 D MDSYS 46
04-JAN-10 11.28.50 AM 0300280024190000 D ORDSYS 43
04-JAN-10 11.28.50 AM 0300280024190000 D EXFSYS 34
04-JAN-10 11.28.50 AM 0300280024190000 D DMSYS 35
04-JAN-10 11.28.50 AM 0300280024190000 D DBSNMP 24
04-JAN-10 11.28.50 AM 0300280024190000 D WMSYS 25
04-JAN-10 11.28.50 AM 0300280024190000 D CTXSYS 36
04-JAN-10 11.28.50 AM 0300280024190000 D ANONYMOUS 39
04-JAN-10 11.28.50 AM 0300280024190000 D SYSMAN 51
04-JAN-10 11.28.50 AM 0300280024190000 D XDB 38
04-JAN-10 11.28.50 AM 0300280024190000 D ORDPLUGINS 44
04-JAN-10 11.28.50 AM 0300280024190000 D SI_INFORMTN_SCHEMA 45
04-JAN-10 11.28.50 AM 0300280024190000 D OLAPSYS 47
04-JAN-10 11.28.50 AM 0300280024190000 D SCOTT 54
04-JAN-10 11.28.50 AM 0300280024190000 D T3 70
04-JAN-10 11.28.50 AM 0300280024190000 D TSMSYS 21
04-JAN-10 11.28.50 AM 0300280024190000 D T6 74
04-JAN-10 11.28.50 AM 0300280024190000 D T1 68
04-JAN-10 11.28.50 AM 0300280024190000 D SQLLDR 75
04-JAN-10 11.28.50 AM 0300280024190000 D T5 73
04-JAN-10 11.28.50 AM 0300280024190000 D BI 60
04-JAN-10 11.28.50 AM 0300280024190000 D T4 72
04-JAN-10 11.28.50 AM 0300280024190000 D PM 59
04-JAN-10 11.28.50 AM 0300280024190000 D MDDATA 50
04-JAN-10 11.28.50 AM 0300280024190000 D IX 57
04-JAN-10 11.28.50 AM 0300280024190000 D SH 58
04-JAN-10 11.28.50 AM 0300280024190000 D DIP 19
04-JAN-10 11.28.50 AM 0300280024190000 D OE 56
04-JAN-10 11.28.50 AM 0300280024190000 D HR 55
04-JAN-10 11.28.50 AM 0300280024190000 D PERFSTAT 62
04-JAN-10 11.28.50 AM 0300280024190000 D T2 69
04-JAN-10 11.28.50 AM 0300280024190000 D RMAN 71
04-JAN-10 11.28.29 AM 0700190084200000 U TQ 6
04-JAN-10 11.28.29 AM TQ 76
04-JAN-10 11.28.50 AM RMAN 71
04-JAN-10 11.28.50 AM T2 69
04-JAN-10 11.28.50 AM PERFSTAT 62
04-JAN-10 11.28.50 AM HR 55
04-JAN-10 11.28.50 AM OE 56
04-JAN-10 11.28.50 AM DIP 19
04-JAN-10 11.28.50 AM SH 58
04-JAN-10 11.28.50 AM IX 57
04-JAN-10 11.28.50 AM MDDATA 50
04-JAN-10 11.28.50 AM PM 59
04-JAN-10 11.28.50 AM T4 72
04-JAN-10 11.28.50 AM BI 60
04-JAN-10 11.28.50 AM T5 73
04-JAN-10 11.28.50 AM SQLLDR 75
04-JAN-10 11.28.50 AM T1 68
04-JAN-10 11.28.50 AM T6 74
04-JAN-10 11.28.50 AM TSMSYS 21
04-JAN-10 11.28.50 AM T3 70
04-JAN-10 11.28.50 AM SCOTT 54
04-JAN-10 11.28.50 AM OLAPSYS 47
04-JAN-10 11.28.50 AM SI_INFORMTN_SCHEMA 45
04-JAN-10 11.28.50 AM ORDPLUGINS 44
04-JAN-10 11.28.50 AM XDB 38
04-JAN-10 11.28.50 AM SYSMAN 51
04-JAN-10 11.28.50 AM ANONYMOUS 39
04-JAN-10 11.28.50 AM CTXSYS 36
04-JAN-10 11.28.50 AM WMSYS 25
04-JAN-10 11.28.50 AM DBSNMP 24
04-JAN-10 11.28.50 AM DMSYS 35
04-JAN-10 11.28.50 AM EXFSYS 34
04-JAN-10 11.28.50 AM ORDSYS 43
04-JAN-10 11.28.50 AM MDSYS 46
SYSTEM 5
SYS 0
04-JAN-10 11.28.50 AM MGMT_VIEW 53
04-JAN-10 11.28.50 AM CSMIG 64
04-JAN-10 11.29.35 AM 07001D0084200000 I DBTAN 8
73 rows selected.
通過以上輸出,根據VERSIONS_XID可以清晰地區分不同事務在不同時間對數據所做的更改。具備了flashback versions query查詢的基礎,就可以進行基於flashback versions query的事務級恢復,這就是flashback transaction query。
flashback transaction query可以從FLASHBACK_TRANSACTION_QUERY視圖中獲得指定事務級的歷史信息以及Undo_SQL,通過這個UNDO_SQL,就可以撤銷特定的提交事務。
flashback transaction query需要用到FLASHBACK_TRANSACTION_QUERY視圖,先看一下視圖:
sys@TQGZS> desc flashback_transaction_query;
Name Null? Type
----------------------- -------- ------------------------
XID RAW(8)
START_SCN NUMBER
START_TIMESTAMP DATE
COMMIT_SCN NUMBER
COMMIT_TIMESTAMP DATE
LOGON_USER VARCHAR2(30)
UNDO_CHANGE# NUMBER
OPERATION VARCHAR2(32)
TABLE_NAME VARCHAR2(256)
TABLE_OWNER VARCHAR2(32)
ROW_ID VARCHAR2(19)
UNDO_SQL VARCHAR2(4000)
該視圖的定義爲:
sys@TQGZS> select dbms_metadata.get_ddl('VIEW','FLASHBACK_TRANSACTION_QUERY') from dual;
DBMS_METADATA.GET_DDL('VIEW','FLASHBACK_TRANSACTION_QUERY')
--------------------------------------------------------------------------------CREATE OR REPLACE FORCE VIEW "SYS"."FLASHBACK_TRANSACTION_QUERY" ("XID", "STAR
T_SCN", "START_TIMESTAMP", "COMMIT_SCN", "COMMIT_TIMESTAMP", "LOGON_USER", "UNDO
_CHANGE#", "OPERATION", "TABLE_NAME", "TABLE_OWNER", "ROW_ID", "UNDO_SQL") AS
select xid, start_scn, start_timestamp,
decode(commit_scn, 0, commit_scn, 281474976710655, NULL, commit_scn)
commit_scn, commit_timestamp,
logon_user, undo_change#, operation, table_name, table_owner,
row_id, undo_sql
from sys.x$ktuqqry
繼續前面的測試,如果需要撤銷XID=0300280024190000的事務,可以通過如下步驟進行(注意當查詢FLASHBACK_TRANSACTION_QUERY視圖時如果直接引用XID則查詢會因爲無法使用索引而極其耗時):
tq@TQGZS> set timing on
tq@TQGZS> set autotrace on
tq@TQGZS> select undo_sql from flashback_transaction_query
2 where xid = '0300280024190000';
UNDO_SQL
--------------------------------------------------------------------------------
insert into "TQ"."T"("USERNAME","USER_ID") values ('CSMIG','64');
insert into "TQ"."T"("USERNAME","USER_ID") values ('MGMT_VIEW','53');
insert into "TQ"."T"("USERNAME","USER_ID") values ('MDSYS','46');
insert into "TQ"."T"("USERNAME","USER_ID") values ('ORDSYS','43');
insert into "TQ"."T"("USERNAME","USER_ID") values ('EXFSYS','34');
insert into "TQ"."T"("USERNAME","USER_ID") values ('DMSYS','35');
insert into "TQ"."T"("USERNAME","USER_ID") values ('DBSNMP','24');
insert into "TQ"."T"("USERNAME","USER_ID") values ('WMSYS','25');
insert into "TQ"."T"("USERNAME","USER_ID") values ('CTXSYS','36');
insert into "TQ"."T"("USERNAME","USER_ID") values ('ANONYMOUS','39');
insert into "TQ"."T"("USERNAME","USER_ID") values ('SYSMAN','51');
insert into "TQ"."T"("USERNAME","USER_ID") values ('XDB','38');
insert into "TQ"."T"("USERNAME","USER_ID") values ('ORDPLUGINS','44');
insert into "TQ"."T"("USERNAME","USER_ID") values ('SI_INFORMTN_SCHEMA','45');
insert into "TQ"."T"("USERNAME","USER_ID") values ('OLAPSYS','47');
insert into "TQ"."T"("USERNAME","USER_ID") values ('SCOTT','54');
insert into "TQ"."T"("USERNAME","USER_ID") values ('T3','70');
insert into "TQ"."T"("USERNAME","USER_ID") values ('TSMSYS','21');
insert into "TQ"."T"("USERNAME","USER_ID") values ('T6','74');
insert into "TQ"."T"("USERNAME","USER_ID") values ('T1','68');
insert into "TQ"."T"("USERNAME","USER_ID") values ('SQLLDR','75');
insert into "TQ"."T"("USERNAME","USER_ID") values ('T5','73');
insert into "TQ"."T"("USERNAME","USER_ID") values ('BI','60');
insert into "TQ"."T"("USERNAME","USER_ID") values ('T4','72');
insert into "TQ"."T"("USERNAME","USER_ID") values ('PM','59');
insert into "TQ"."T"("USERNAME","USER_ID") values ('MDDATA','50');
insert into "TQ"."T"("USERNAME","USER_ID") values ('IX','57');
insert into "TQ"."T"("USERNAME","USER_ID") values ('SH','58');
insert into "TQ"."T"("USERNAME","USER_ID") values ('DIP','19');
insert into "TQ"."T"("USERNAME","USER_ID") values ('OE','56');
insert into "TQ"."T"("USERNAME","USER_ID") values ('HR','55');
insert into "TQ"."T"("USERNAME","USER_ID") values ('PERFSTAT','62');
insert into "TQ"."T"("USERNAME","USER_ID") values ('T2','69');
insert into "TQ"."T"("USERNAME","USER_ID") values ('RMAN','71');
35 rows selected.
Elapsed: 00:00:22.71
Execution Plan
----------------------------------------------------------
Plan hash value: 1115820779
--------------------------------------
| Id | Operation | Name |
--------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | FIXED TABLE FULL| X$KTUQQRY |
--------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(RAWTOHEX("XID")='0300280024190000')
Note
-----
- rule based optimizer used (consider using cbo)
Statistics
----------------------------------------------------------
28346 recursive calls
0 db block gets
1082754 consistent gets
2 physical reads
0 redo size
3036 bytes sent via SQL*Net to client
407 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
255 sorts (memory)
0 sorts (disk)
35 rows processed
此時可以通過hextoraw轉換利用底層索引,提高查詢速度:
tq@TQGZS> set autotrace traceonly explain
tq@TQGZS> select undo_sql from flashback_transaction_query
2 where xid = hextoraw('0300280024190000');
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 1747778896
-----------------------------------------------------
| Id | Operation | Name |
-----------------------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | FIXED TABLE FIXED INDEX| X$KTUQQRY (ind:1) |
-----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("XID"=HEXTORAW('0300280024190000') )
Note
-----
- rule based optimizer used (consider using cbo)
通過執行相應的UNDO語句可以撤銷該事務,通過這些新特性,Oracle提供了一種“回滾”提交事務的手段,極大地方便了用戶應對不同情況的數據庫恢復。