about flashback_transaction_query
本站文章除注明转载外,均为本站原创: 转载自love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客
前几天某大师提醒我说了,我以前一篇文档flashback_transaction_query 查询慢的问题 有点问题。 现在回想一下,确实不太对,
虽然以前的方法也是一种处理方法然而有点偏离方向了。首先我们来看一下试图的定义:
—definition
1 2 3 4 5 6 7 8 9 |
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 |
可以看到,该试图的本质是访问x$ktuqqry. 那么这个试图是干什么的呢?显然是闪回事务查询的时候需要用到的东西,而且访问的
的数据是来自undo.下面我们随便从该试图中取一个xid来重现一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
SQL> select xid from FLASHBACK_TRANSACTION_QUERY where rownum < 2; XID ---------------- 0C0012008F030000 SQL> select count(1) from FLASHBACK_TRANSACTION_QUERY where xid='0C0012008F030000'; select count(1) from FLASHBACK_TRANSACTION_QUERY where xid='0C0012008F030000' * ERROR at line 1: ORA-01013: user requested cancel of current operation Elapsed: 00:01:14.06 |
可以发现访问很慢,为什么呢 ?我们先来看下执行计划:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
SQL> set autot traceonly exp SQL> select count(1) from FLASHBACK_TRANSACTION_QUERY where xid='0C0012008F030000'; Elapsed: 00:00:00.02 Execution Plan ---------------------------------------------------------- Plan hash value: 3839279163 ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 9 | 0 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 9 | | | |* 2 | FIXED TABLE FULL| X$KTUQQRY | 1 | 9 | 0 (0)| 00:00:01 | ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(RAWTOHEX("XID")='0C0012008F030000') SQL> set autot off |
可以发现,id 2的地方走了table full scan,也就是全表扫描. 以前没用注意的一个细节.大家注意看下面的filter部分,很明显是
进行了隐式转换,以至于走full table scan了。 这里用的rwatohex进行了转换,那么如果使用hextoraw进行反向转一下呢 ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
SQL> select count(1) from FLASHBACK_TRANSACTION_QUERY where xid=hextoraw('0C0012008F030000'); COUNT(1) ---------- 8 Elapsed: 00:00:00.01 SQL> set autot on SQL> select count(1) from FLASHBACK_TRANSACTION_QUERY where xid=hextoraw('0C0012008F030000'); COUNT(1) ---------- 8 Elapsed: 00:00:00.02 Execution Plan ---------------------------------------------------------- Plan hash value: 728944840 ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 9 | 0 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 9 | | | |* 2 | FIXED TABLE FIXED INDEX| X$KTUQQRY (ind:1) | 1 | 9 | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("XID"=HEXTORAW('0C0012008F030000') ) Statistics ---------------------------------------------------------- 25 recursive calls 0 db block gets 51 consistent gets 0 physical reads 0 redo size 411 bytes sent via SQL*Net to client 400 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 4 sorts (memory) 0 sorts (disk) 1 rows processed |
可以发现,这样的话,速度非常之快. 原来以前一直犯了一个错误,误导了不少人啊. 自我批评下.
到这里可能很多人以为这篇文章到此结束了,是吗? 实际上,故事才刚刚开始….
或许有些网友已经想到了,这个试图是干吗的?闪回查询,那么如何去定位到这个xid号呢 ?
假如1分钟之前某人删除了一条记录,那么我们要通过闪回事务去恢复这条数据,如何去进行恢复呢 ? 我们可以直接通过
查询该试图来获取undo_sql 进行恢复,其关键是如何获得该操作的XID ?
+++++++++ 方法1 闪回查询 +++++++++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'; Session altered. SQL> select sysdate from dual; SYSDATE ------------------- 2013-06-30 04:52:48 SQL> select scn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss')from sys.smon_scn_time 2 where to_char(time_dp,'yyyy-mm-dd hh24:mi:ss') > '2013-06-30 04:40:00' order by 2; SCN TO_CHAR(TIME_DP,'YY ---------- ------------------- 8560772 2013-06-30 04:44:56 SQL> select current_scn from v$database; CURRENT_SCN ----------- 8561007 SQL> col versions_starttime for a35 SQL> col versions_endtime for a35 SQL> select * from ( 2 select versions_starttime, versions_endtime, versions_xid, versions_operation,object_id 3 from roger.test_undo1 versions between timestamp minvalue and maxvalue order by 5 desc) where rownum < 5; VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_XID V OBJECT_ID ----------------------------------- ----------------------------------- ---------------- - ---------- 30-JUN-13 04.23.43 AM 0C0012008F030000 D 1051 24-JUN-13 06.25.10 AM 30-JUN-13 04.23.43 AM 15000C0084030000 I 1051 1050 1049 |
这里的versions_xid,就表示该事务的xid,其中versions_operaition表示操作类型:D表示delete,I表示insert,U表示update.
通过该xid,我们可以直接查询undo_sql,然后执行该sql文本就可以将该条删除的数据恢复回来,如下查询:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
SQL> select undo_sql from FLASHBACK_TRANSACTION_QUERY 2 where xid=hextoraw('0C0012008F030000'); UNDO_SQL -------------------------------------------------------------------------------------------------------------------------- /* No SQL_UNDO for temporary tables */ /* No SQL_UNDO for temporary tables */ /* No SQL_UNDO for temporary tables */ delete from "SYS"."PLAN_TABLE$" where ROWID = 'AAQAIJAABAAAAIKAAC'; delete from "SYS"."PLAN_TABLE$" where ROWID = 'AAQAIJAABAAAAIKAAB'; delete from "SYS"."PLAN_TABLE$" where ROWID = 'AAQAIJAABAAAAIKAAA'; insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATE D","LAST_DDL_TIME","TIMESTAMP","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('PUBLIC','V$_LOCK',NULL,'1051',NULL,' SYNONYM',TO_DATE('15-APR-10', 'DD-MON-RR'),TO_DATE('15-APR-10', 'DD-MON-RR'),'2010-04-15:13:15:01','VALID','N','N','N'); |
实际上我们利用该视图来定位undo_sql,关键的地方是定位到具体的xid。
那么针对一个表的操作,可能有很多,我们如何去定位呢? 其实完全可以结合scn和operation以及table_name,table_owner来缩小范围.
类似如下的操作:
SQL> select XID,OPERATION,UNDO_CHANGE#,TABLE_NAME,TABLE_OWNER,ROW_ID
2 from FLASHBACK_TRANSACTION_QUERY where table_name=’TEST_UNDO1′ and table_owner=’ROGER’ and row_id >’AAAPJyAACAAAR/vABN’;
当然如果由于该x$表仅仅在xid字段上存在索引,索引这样查询,可能会比较慢.如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
SQL> l 1 select XID,OPERATION,UNDO_CHANGE#,TABLE_NAME,TABLE_OWNER,ROW_ID 2* from FLASHBACK_TRANSACTION_QUERY where table_name='TEST_UNDO1' and table_owner='ROGER' and row_id >'AAAPJyAACAAAR/vABN' SQL> / XID OPERATION UNDO_CHANGE# TABLE_NAME TABLE_OWNE ROW_ID ---------------- -------------------------------- ------------ ---------- ---------- ------------------- 0C0012008F030000 DELETE 7 TEST_UNDO1 ROGER AAAPJyAACAAAR/wAAA 140013009C030000 DELETE 1 TEST_UNDO1 ROGER AAAPJyAACAAAR/vABO 15000C0084030000 INSERT 1 TEST_UNDO1 ROGER AAAPJyAACAAAR/wAAA Elapsed: 00:02:10.59 |
显然这里我们根据判断知道第1条信息是我们所需要的.
++++++++++ 方法2 根据rowid 边界定位xid ++++++++++
除了利用闪回的方法,是否还有其他方法呢?假如我删除掉一个范围的数据,例如:
1 2 3 4 5 6 7 8 9 10 |
--Session 1 SQL> show user USER is "ROGER" SQL> delete from test_undo1 where object_id > 300 and object_id < 400; 90 rows deleted. SQL> commit; Commit complete. |
不考虑边界的问题,某条数据通常会跟其他数据存在同一block中,所以根据删除的数据范围,定位到block 号:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
SQL> select rowid, 2 dbms_rowid.rowid_object(rowid) object_id, 3 dbms_rowid.rowid_relative_fno(rowid) file_id, 4 dbms_rowid.rowid_block_number(rowid) block_id, 5 dbms_rowid.rowid_row_number(rowid) num, 6 rowidtochar(rowid) 7 from roger.test_undo1 where object_id=300; ROWID OBJECT_ID FILE_ID BLOCK_ID NUM ROWIDTOCHAR(ROWID) ------------------ ---------- ---------- ---------- ---------- ------------------ AAAPJyAACAAAR/nAAV 62066 2 73703 21 AAAPJyAACAAAR/nAAV Elapsed: 00:00:00.01 SQL> select rowid, 2 dbms_rowid.rowid_object(rowid) object_id, 3 dbms_rowid.rowid_relative_fno(rowid) file_id, 4 dbms_rowid.rowid_block_number(rowid) block_id, 5 dbms_rowid.rowid_row_number(rowid) num, 6 rowidtochar(rowid) 7 from roger.test_undo1 where object_id=400; ROWID OBJECT_ID FILE_ID BLOCK_ID NUM ROWIDTOCHAR(ROWID) ------------------ ---------- ---------- ---------- ---------- ------------------ AAAPJyAACAAAR/oAAd 62066 2 73704 29 AAAPJyAACAAAR/oAAd Elapsed: 00:00:00.02 SQL> ---Session 2 SQL> conn /as sysdba Connected. SQL> oradebug setmypid Statement processed. SQL> alter system dump datafile 2 block 73703 2 / System altered. SQL> alter system dump datafile 2 block 73704; System altered. SQL> oradebug close_trace Statement processed. SQL> oradebug tracefile_name /home/ora10g/admin/roger/udump/roger_ora_14279.trc |
此时roger_ora_14279.trc 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
Block header dump: 0x00811fe7 Object id on Block? Y seg/obj: 0xf272 csc: 0x00.7f0cc2 itc: 3 flg: E typ: 1 - DATA brn: 0 bdba: 0x811fe1 ver: 0x01 opc: 0 inc: 0 exflg: 0 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.007f0cc2 0x02 0x000c.011.0000038f 0x0180608c.0734.02 --U- 61 fsc 0x1388.00837f8d 0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 data_block_dump,data header at 0xd0da87c =============== tsiz: 0x1f80 hsiz: 0xb8 pbl: 0x0d0da87c bdba: 0x00811fe7 76543210 ......... Block header dump: 0x00811fe8 Object id on Block? Y seg/obj: 0xf272 csc: 0x00.7f0cc2 itc: 3 flg: E typ: 1 - DATA brn: 0 bdba: 0x811fe1 ver: 0x01 opc: 0 inc: 0 exflg: 0 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.007f0cc2 0x02 0x000c.011.0000038f 0x0180608c.0734.1f --U- 29 fsc 0x08de.00837f8d 0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 data_block_dump,data header at 0xd0da87c =============== tsiz: 0x1f80 hsiz: 0xc0 pbl: 0x0d0da87c bdba: 0x00811fe8 76543210 ...... |
从上面2个block的dump可以看出xid 信息如下:
0x000c.011.0000038f
0x000c.011.0000038f 虽然涉及到多个block的操作,但是仍然是同一个事务.所以这里xid的一个值.
将其转换为FLASHBACK_TRANSACTION_QUERY.xid的格式,其长度为16位,不足的部分用0补齐.
0c00 1100 8f030000 即使xid=0c0011008f030000
获取到xid后,直接生成恢复的脚本即可,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
SQL> set pagesize 5000 SQL> col undo_sql for a150 SQL> set long 9999999 SQL> spool test_undo1_insert.sql SQL> select undo_sql from FLASHBACK_TRANSACTION_QUERY where xid=hextoraw('0c0011008f030000'); UNDO_SQL ------------------------------------------------------------------------------------------------------------------------------------------------------ insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAM P","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('SYS','SUMDETAIL$',NULL,'399','399','TABLE',TO_DATE('15-APR-10', 'DD-MON-RR'),TO_DATE('15-APR -10', 'DD-MON-RR'),'2010-04-15:13:14:46','VALID','N','N','N'); insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAM P","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('SYS','I_SUM$_1',NULL,'398','398','INDEX',TO_DATE('15-APR-10', 'DD-MON-RR'),TO_DATE('15-APR-1 0', 'DD-MON-RR'),'2010-04-15:13:14:46','VALID','N','N','N'); ....... insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAM P","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('SYS','LOBCOMPPART$',NULL,'302','302','TABLE',TO_DATE('15-APR-10', 'DD-MON-RR'),TO_DATE('15-A PR-10', 'DD-MON-RR'),'2010-04-15:13:14:46','VALID','N','N','N'); insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAM P","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('SYS','I_LOBFRAG$_FRAGOBJ$',NULL,'301','301','INDEX',TO_DATE('15-APR-10', 'DD-MON-RR'),TO_DAT E('15-APR-10', 'DD-MON-RR'),'2010-04-15:13:14:46','VALID','N','N','N'); 91 rows selected. Elapsed: 00:00:00.06 SQL> spool off SQL> SQL> ! [ora10g@killdb ~]$ pwd /home/ora10g [ora10g@killdb ~]$ cat test_undo1_insert.sql |grep insert|wc -l 90 [ora10g@killdb ~]$ |
++++++++++++ 方法 3 使用bbed 定位XID
如果操作的数据刚好都在一个block,即一共block内数据被全部删除,那么无法通过第2种的边界方法去定位.
首先我这里用一个例子来展示,将一个block的数据全部delete掉,但是需要先定位到该block的数据范围:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
BBED> set file 2 block 73705 FILE# 2 BLOCK# 73705 BBED> p kdbr sb2 kdbr[0] @142 7981 sb2 kdbr[1] @144 7893 ...... sb2 kdbr[80] @302 1115 sb2 kdbr[81] @304 1021 BBED> p *kdbr[0] rowdata[7048] ------------- ub1 rowdata[7048] @8105 0x2c BBED> x /rccccccccccccccccccccccccccccc rowdata[7048] @8105 ------------- flag@8105: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@8106: 0x00 cols@8107: 13 col 0[5] @8108: OUTLN col 1[10] @8114: OL$HNT_NUM col 2[0] @8125: *NULL* col 3[3] @8126: < col 4[3] @8130: < col 5[5] @8134: INDEX col 6[7] @8140: xn....0 col 7[7] @8148: xn....0 col 8[19] @8156: 2010-04-15:13:14:47 col 9[5] @8176: VALID col 10[1] @8182: N col 11[1] @8184: N col 12[1] @8186: N BBED> x /rnnnnnnnnnnnnnnnnnnnnnnn rowdata[7048] @8105 ------------- flag@8105: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@8106: 0x00 cols@8107: 13 col 0[5] @8108: ######################################### col 1[10] @8114: ######################################### col 2[0] @8125: *NULL* col 3[3] @8126: 459 col 4[3] @8130: 459 col 5[5] @8134: ######################################### col 6[7] @8140: ######################################### col 7[7] @8148: ######################################### col 8[19] @8156: ######################################### col 9[5] @8176: ######################################### col 10[1] @8182: ######################################### col 11[1] @8184: ######################################### col 12[1] @8186: ######################################### BBED> p *kdbr[81] rowdata[88] ----------- ub1 rowdata[88] @1145 0x2c BBED> x /rnnnnnnnnnnnnnnnnnnnn rowdata[88] @1145 ----------- flag@1145: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@1146: 0x00 cols@1147: 13 col 0[3] @1148: ######################################### col 1[25] @1152: 0x53 0x59 0x53 0x5f 0x4c 0x4f 0x42 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x35 0x34 0x35 0x43 0x30 0x30 0x30 0x30 0x33 0x24 0x24 col 2[0] @1178: *NULL* col 3[3] @1179: 546 col 4[3] @1183: 546 col 5[3] @1187: ######################################### col 6[7] @1191: ######################################### col 7[7] @1199: ######################################### col 8[19] @1207: ######################################### col 9[5] @1227: ######################################### col 10[1] @1233: ######################################### col 11[1] @1235: ######################################### |
从上面可以看出,该block内的数据范围在object_id 459和546之间,将其全部delete掉:
1 2 3 4 5 6 7 8 9 10 11 |
SQL> show user USER is "ROGER" SQL> delete from test_undo1 where object_id >=459 and object_id <=546; 82 rows deleted. SQL> commit; Commit complete. SQL> |
通过bbed来获取xid,首先观察操作前后的itl信息变化,如下:
—-delete操作之后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
struct ktbbhitl[0], 24 bytes @44 struct ktbitxid, 8 bytes @44 ub2 kxidusn @44 0xffff ub2 kxidslt @46 0x0000 ub4 kxidsqn @48 0x00000000 struct ktbituba, 8 bytes @52 ub4 kubadba @52 0x00000000 ub2 kubaseq @56 0x0000 ub1 kubarec @58 0x00 ub2 ktbitflg @60 0x8000 (KTBFCOM) union _ktbitun, 2 bytes @62 b2 _ktbitfsc @62 0 ub2 _ktbitwrp @62 0x0000 ub4 ktbitbas @64 0x007f0cc2 struct ktbbhitl[1], 24 bytes @68 struct ktbitxid, 8 bytes @68 ub2 kxidusn @68 0x000e ub2 kxidslt @70 0x002d ub4 kxidsqn @72 0x00000395 struct ktbituba, 8 bytes @76 ub4 kubadba @76 0x0180504f ub2 kubaseq @80 0x0995 ub1 kubarec @82 0x12 ub2 ktbitflg @84 0x8000 (KTBFCOM) union _ktbitun, 2 bytes @86 b2 _ktbitfsc @86 0 ub2 _ktbitwrp @86 0x0000 ub4 ktbitbas @88 0x007f342a struct ktbbhitl[2], 24 bytes @92 struct ktbitxid, 8 bytes @92 ub2 kxidusn @92 0x0014 ub2 kxidslt @94 0x0003 ub4 kxidsqn @96 0x0000039d struct ktbituba, 8 bytes @100 ub4 kubadba @100 0x018017ba ub2 kubaseq @104 0x0855 ub1 kubarec @106 0x0b ub2 ktbitflg @108 0x2052 (KTBFUPB) union _ktbitun, 2 bytes @110 b2 _ktbitfsc @110 6881 ub2 _ktbitwrp @110 0x1ae1 ub4 ktbitbas @112 0x00838226 |
在不考虑ITL被覆盖的情况下,显然该事务所使用的itl应该是最后一个.
从这里我们可以看出对应的事务XID为:0x0014 0003 0000039d
转换为FLASHBACK_TRANSACTION_QUERY试图的标准xid格式为:140003009d030000
获得到xid后,我们就可以直接查询获得undo_sql文本了,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
SQL> spool test_undo1_insert2.sql SQL> select undo_sql from FLASHBACK_TRANSACTION_QUERY where xid=hextoraw('140003009d030000'); UNDO_SQL ------------------------------------------------------------------------------------------------------------------------------------------------------ insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAM P","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('SYS','SYS_LOB0000000545C00003$$',NULL,'546','546','LOB',TO_DATE('15-APR-10', 'DD-MON-RR'),TO _DATE('15-APR-10', 'DD-MON-RR'),'2010-04-15:13:14:49','VALID','N','Y','N'); ...... insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAM P","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('OUTLN','OL$NODE_OL_NAME',NULL,'460','460','INDEX',TO_DATE('15-APR-10', 'DD-MON-RR'),TO_DATE( '15-APR-10', 'DD-MON-RR'),'2010-04-15:13:14:47','VALID','N','N','N'); insert into "ROGER"."TEST_UNDO1"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJECT_TYPE","CREATED","LAST_DDL_TIME","TIMESTAM P","STATUS","TEMPORARY","GENERATED","SECONDARY") values ('OUTLN','OL$HNT_NUM',NULL,'459','459','INDEX',TO_DATE('15-APR-10', 'DD-MON-RR'),TO_DATE('15-A PR-10', 'DD-MON-RR'),'2010-04-15:13:14:47','VALID','N','N','N'); 83 rows selected. Elapsed: 00:00:00.03 SQL> spool off SQL> ! [ora10g@killdb ~]$ cat test_undo1_insert2.sql |grep insert|wc -l 82 [ora10g@killdb ~]$ |
我们可以发现,刚好82条记录,也就是该block中被删除的所有记录,一共82条.
备注: 本文不考虑block itl被覆盖的情况,如果block itl被覆盖,那么情况更为复制,大家可以一起研究下.
One Response to “about flashback_transaction_query”
[…] 详见原文博客链接地址:about flashback_transaction_query 本文链接: about flashback_transaction_query 版权所有: 非特殊声明均为本站原创文章,转载请注明出处:开发者 订阅更新: 您可以通过RSS订阅我们的内容更新 […]
Leave a Reply
You must be logged in to post a comment.