oracle的回闪查询

oracle回闪查询的新特性

从oracle9i开始,oracle开始提供回闪查询特性(flashback query),允许将回滚段中的数据进行回闪,通过下面的例子来看一下这个从oracle9i开始提供的新特性.

SQL> update emp set sal=4000 where empno=7788;

1 row updated.
SQL> update emp set sal=4000 where empno=7782;

1 row updated.

SQL> update emp set sal=4000 where empno=7698;

1 row updated.

先不提交这个事务,在另外窗口新开session,使用sys用户查询相关信息,进行进一步的分析

获得事务信息
从事务表中可以获得关于这个事务的信息,该事务位于9号回滚段(XIDUSN),在9号回滚段
上,该事务位于第29号事务槽(XIDSLOT):

SQL> select xidusn,xidslot,xidsqn,ubablk,ubafil,ubarec from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN     UBABLK     UBAFIL     UBAREC
---------- ---------- ---------- ---------- ---------- ----------
         9         29        385       1350          2         22

从v$rollstat视图中也可获得事务信息,xacts字段代表的是活动事务的数量,同样看到该事务
位于9号回滚段

SQL> select usn,writes,rssize,xacts,hwmsize,shrinks,wraps from v$rollstat;

       USN     WRITES     RSSIZE      XACTS    HWMSIZE    SHRINKS      WRAPS
---------- ---------- ---------- ---------- ---------- ---------- ----------
         0       7620     385024          0     385024          0          0
         1      21390   29351936          0   29351936          0          0
         2      22108    3268608          0    3268608          0          0
         3      29954     450560          0     450560          0          0
         4      23700     843776          0     843776          0          0
         5      23334     450560          0     450560          0          0
         6      21082     450560          0     450560          0          0
         7      23146    2285568          0    2285568          0          0
         8      28742     843776          0     843776          0          1
         9      22648    2088960          1    2088960          0          0
        10      24326    2220032          0    2220032          0          0

11 rows selected.

这是执行alter system dump datafile 2 block 1350
转储的回滚表空间中的数据块的信息的一部分

*-----------------------------
* Rec #0x1d  slt: 0x24  objn: 517(0x00000205)  objd: 517  tblspc: 0(0x00000000)
*       Layer:  11 (Row)   opc: 1   rci 0x00
Undo type:  Regular undo    Begin trans    Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
rdba: 0x00000000
*-----------------------------
uba: 0x00800546.0129.1b ctl max scn: 0x0000.000e4e9c prv tx scn: 0x0000.000e4ea6
txn start scn: scn: 0x0000.000e7526 logon user: 0
 prev brb: 8389956 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x04  ver: 0x01
op: L  itl: xid:  0x0006.016.0000015d uba: 0x00800419.00fe.11
                      flg: C---    lkc:  0     scn: 0x0000.000e7524
KDO Op code: URP row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x0040100f  hdba: 0x00401001
itli: 2  ispac: 0  maxfr: 4863
tabn: 0 slot: 116(0x74) flag: 0x2c lock: 0 ckix: 191
ncol: 9 nnew: 7 size: 0
Vector content:
col  2: [ 2]  c1 0a
col  3: [ 2]  c1 0a
col  4: [ 1]  80
col  5: [ 1]  80
col  6: [ 1]  80
col  7: [ 1]  80
col  8: [ 7]  78 71 01 07 0b 07 34

先注意到这里存在一个信息ctl max scn: 0x0000.000e4e9c,这个转换为scn值就是:

SQL> select (to_number('000','xxxx')*power(2,32)+to_number('e4e9c','xxxxxxxx')) scn
from dual;

       SCN
----------
    937628

查询一下当前数据的scn:

SQL> select dbms_flashback.get_system_change_number scn from dual;

       SCN
----------
    949630

SQL>

通过特定的语法,可以将scn 937628的历史状态数据查询出来:

SQL> select * from scott.emp as of scn 937628 where empno in(7788,7782,7698);

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
 7698 BLAKE      MANAGER    7839 1981-5-1      2850.00               30
 7782 CLARK      MANAGER    7839 1981-6-9      2450.00               10
 7788 SCOTT      ANALYST    7566 1987-4-19       10.00               20

在查询结果中,注意到3名员工的薪水恢复到了之前的状态.而在当前的查询中,这个数据是变化
后的4000:

SQL> select * from scott.emp  where empno in(7788,7782,7698);

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
 7698 BLAKE      MANAGER    7839 1981-5-1      4000.00               30
 7782 CLARK      MANAGER    7839 1981-6-9      4000.00               10
 7788 SCOTT      ANALYST    7566 1987-4-19     4000.00               20

由于这个查询需要从undo中获限前镜像信息,如果undo中的信息被覆盖,则以上查询将会失败.
测试一下,当新建undo表空间,切换undo表空间,再将原表空间offline之后:

SQL> create undo tablespace undotbs2 datafile
  2  '/u01/app/oracle/product/10.2.0/oradata/jingyong/undotbs02.dbf' size 10M;

Tablespace created


SQL> alter system set undo_tablespace=undotbs2;

System altered.

SQL> alter tablespace undotbs1 offline;

Tablespace altered.

SQL> alter session set events='immediate trace name flush_cache';

Session altered.

再来查询,此时出现错误,记录该文件已经不可读取:

SQL> select * from scott.emp as of scn 937628 where empno in(7788,7782,7698);

select * from scott.emp as of scn 937628 where empno in(7788,7782,7698)

ORA-00376: file 2 cannot be read at this time
ORA-01110: data file 2: '/u01/app/oracle/product/10.2.0/oradata/jingyong/undotbs01.dbf'

将undotbs1重新启用:

SQL> alter tablespace undotbs1 online;

Tablespace altered.

SQL> alter system set undo_tablespace=undotbs1;

System altered.

此时前镜像信息再次可以查询,

SQL> select * from scott.emp as of scn 937628 where empno in(7788,7782,7698);

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
 7698 BLAKE      MANAGER    7839 1981-5-1      2850.00               30
 7782 CLARK      MANAGER    7839 1981-6-9      2450.00               10
 7788 SCOTT      ANALYST    7566 1987-4-19       10.00               20

如果在其他session中执行大量事务,使用前镜像信息被覆盖:
在执行其它大量事务之前观察回滚段的使用情况:

SQL> select usn,xacts,rssize,hwmsize from v$rollstat where usn=9;

       USN      XACTS     RSSIZE    HWMSIZE
---------- ---------- ---------- ----------
         9          0    2088960    2088960


SQL> begin
  2  for i in 1..2000 loop
  3   update scott.emp set sal=4000;
  4   rollback;
  5  end loop;
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> select usn,xacts,rssize,hwmsize from v$rollstat where usn=9;

       USN      XACTS     RSSIZE    HWMSIZE
---------- ---------- ---------- ----------
         9          1    4186112    4186112

那么再次查询就可能会收到如下错误:

SQL> select * from scott.emp as of scn 937628 where empno in(7788,7782,7698);
select * from scott.emp as of scn 937628 where empno in(7788,7782,7698)
ERROR at line 1:
ORA-01555: snapshot too old:rollback segment number 9 with name "_SYSSMU9$" too small

ORA-01555错误出现说明要查询的前镜偈信息已经丢失了.

使用errorstack进行错误跟踪
errorstack是oracle提供的接口用于诊断oracle的错误信息.

诊断事件可以在session级设置,也可以在系统级设置,通常如果要诊断全局错误,最好在
系统级设置.设置了errorstack事件之后,oracle会将出错时的信息记入跟踪文件中.
用户就可以通过跟踪文件进行错误诊断和排查.

可以通过errorstack事件来跟踪ora-01555错误:

OS Pid: 2928 executed alter session set events '1555 trace name errorstack level 4'
ORA-01555 caused by SQL statement below (SQL ID: bnaqc462nnjtb, Query Duration=0 sec, SCN: 0x0000.00068478):
Mon Jan  7 20:23:35 2013
select * from scott.emp as of scn 427128 where empno in(7788,7782,7698)
Mon Jan  7 20:23:35 2013
Errors in file /u01/app/oracle/admin/jingyong/udump/jingyong_ora_2928.trc:
ORA-01555: snapshot too old: rollback segment number 3 with name "???" too small

这里注意到,触发ora-01555错误的语句被记录,出现错误的scn也被记录,这个scn:0x0000.00068478
找到jingyong_ora_2928.trc跟踪文件,就可以获得关于这次错误的相关信息用于诊断.
错误信息如下

ksedmp: internal or fatal error
ORA-01555: snapshot too old: rollback segment number 3 with name "???" too small
Current SQL statement for this session:
select * from scott.emp as of scn 427128 where empno in(7788,7782,7698)

数据块信息,这里的块头就包含了ITL信息,根据这个ITL信息中的UBA,oracle可以定位回滚段.
查询前镜像信息,如果不存在,就可能出现ora-01555错误

Block header dump:  0x01000024
 Object id on Block? Y
 seg/obj: 0xc7cd  csc: 0x00.6bfcb  itc: 2  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x1000021 ver: 0x01 opc: 0
     inc: 0  exflg: 0

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0x0003.011.000000f2  0x00805794.00c8.4a  --U-   14  fsc 0x0000.0006bfdb

oracle 10g回闪查询特性的增强
oracle9i提供的闪回特性增强,为恢复带来了极大的方便,但是oracle9i的回闪查询只能提供某个
时间点的数据视图,并不能告诉用户这样的数据经过几个事务,怎样被修改的(update,insert,delete)
,而这些信息在回滚段中是存在的,在oracle10g中,oracle进一步加强了回闪查询的特性,提供以下
两种回闪查询:
回闪版本查询(flashback versions query)
回闪事务查询(flashback transaction query)

回闪版本查询允许使用一个新的versions子句查询两个时间点或者scn之间的数据版本.
这些版本可以按照事务进行区分,回闪版本查询只返回提交数据.没提交的数据不被显示

先创建一个测试表,执行一些DML操作

SQL> create table test as select username from dba_users;

Table created.

SQL> select * from test;

USERNAME
------------------------------
MGMT_VIEW
SYS
SYSTEM
DBSNMP
SYSMAN
SCOTT
JYTEST1
JYTEST
OUTLN
MDSYS
ORDSYS

USERNAME
------------------------------
EXFSYS
DMSYS
WMSYS
CTXSYS
ANONYMOUS
XDB
ORDPLUGINS
SI_INFORMTN_SCHEMA
OLAPSYS
TSMSYS
BI

USERNAME
------------------------------
PM
MDDATA
IX
SH
DIP
OE
HR

29 rows selected.

SQL> delete from test where username='BI';

1 row deleted.

SQL> delete from test where username='JYTEST1';

1 row deleted.

SQL> commit;

Commit complete.

SQL> select * from test;

USERNAME
------------------------------
MGMT_VIEW
SYS
SYSTEM
DBSNMP
SYSMAN
SCOTT
JYTEST
OUTLN
MDSYS
ORDSYS
EXFSYS

USERNAME
------------------------------
DMSYS
WMSYS
CTXSYS
ANONYMOUS
XDB
ORDPLUGINS
SI_INFORMTN_SCHEMA
OLAPSYS
TSMSYS
PM
MDDATA

USERNAME
------------------------------
IX
SH
DIP
OE
HR

27 rows selected.

再多执行一些DML操作

SQL> update test set username='JYTEST1' where username='JYTEST';

1 row updated.

SQL> delete from test where username='IX';

1 row deleted.

SQL> commit;

Commit complete.

SQL> select * from test;

USERNAME
------------------------------
MGMT_VIEW
SYS
SYSTEM
DBSNMP
SYSMAN
SCOTT
JYTEST1
OUTLN
MDSYS
ORDSYS
EXFSYS

USERNAME
------------------------------
DMSYS
WMSYS
CTXSYS
ANONYMOUS
XDB
ORDPLUGINS
SI_INFORMTN_SCHEMA
OLAPSYS
TSMSYS
PM
MDDATA

USERNAME
------------------------------
SH
DIP
OE
HR
JY

27 rows selected.

再来看看oracle10g的回闪版本查询,通过使用versions子句,和对数据表引入了一系列的伪列(
version_startime等),可以获得对数据表的所有事务操作,注意以下输出中的versions_operation
代表了不同类型的操作(D-Delete,I-Insert,U-Update),versions_xid是一个重要数据,代表了不
同版本的事务ID:

SQL> select versions_starttime,versions_endtime,versions_xid,versions_operation,
  2  username from test versions between timestamp minvalue and maxvalue;

VERSIONS_STARTTIME           VERSIONS_ENDTIME            VERSIONS_XID     VERSIONS_OPERATION USERNAME
--------------------------- ---------------------------- ---------------- ------------------ ---------------------- --------
07-1月 -13 11.07.58 下午                                 0300150096010000 I                  JY
07-1月 -13 11.06.46 下午                                 06002B0093010000 D                  IX
07-1月 -13 11.06.46 下午                                 06002B0093010000 U                  JYTEST1
07-1月 -13 11.05.22 下午                                 05001E00A7010000 D                  JYTEST1
07-1月 -13 11.05.22 下午                                 05001E00A7010000 D                  BI
                                                                                             MGMT_VIEW
                                                                                             SYS
                                                                                             SYSTEM
                                                                                             DBSNMP
                                                                                             SYSMAN
                                                                                             SCOTT
                            07-1月 -13 11.05.22 下午                                         JYTEST1
                            07-1月 -13 11.06.46 下午                                         JYTEST
                                                                                             OUTLN
                                                                                             MDSYS
                                                                                             ORDSYS
                                                                                             EXFSYS
                                                                                             DMSYS
                                                                                             WMSYS
                                                                                             CTXSYS

VERSIONS_STARTTIME          VERSIONS_ENDTIME             VERSIONS_XID     VERSIONS_OPERATION USERNAME
--------------------------- ---------------------------- ---------------- ------------------ ---------------------- --------
                                                                                             ANONYMOUS
                                                                                             XDB
                                                                                             ORDPLUGINS
                                                                                             SI_INFORMTN_SCHEMA
                                                                                             OLAPSYS
                                                                                             TSMSYS
                            07-1月 -13 11.05.22 下午                                         BI
                                                                                             PM
                                                                                             MDDATA
                            07-1月 -13 11.06.46 下午                                         IX
                                                                                             SH
                                                                                             DIP
                                                                                             OE
                                                                                             HR

34 rows selected

通过以上输出,根据versions_xid可以清晰地区分不同事务在不同时间对数据所作的更改

具备了flashback version query查询的基础,就可以进行基于flashback version query的事务级恢复了.
这就是flashback transaction query, flashback transaction query可以从flashback transaction query
视图中获得指定事务的历史信息以及undo_sql,通过undo_sql,就可以撤消特定的提交事务.flashback
transaction query需要用到flashback_transaction_query视图,先看一下视图:

SQL> desc flashback_transaction_query
Name             Type           Nullable Default Comments
---------------- -------------- -------- ------- -----------------------------------------
XID              RAW(8)         Y                Transaction identifier
START_SCN        NUMBER         Y                Transaction start SCN
START_TIMESTAMP  DATE           Y                Transaction start timestamp
COMMIT_SCN       NUMBER         Y                Transaction commit SCN
COMMIT_TIMESTAMP DATE           Y                Transaction commit timestamp
LOGON_USER       VARCHAR2(30)   Y                Logon user for transaction
UNDO_CHANGE#     NUMBER         Y                1-based undo change number
OPERATION        VARCHAR2(32)   Y                forward operation for this undo
TABLE_NAME       VARCHAR2(256)  Y                table name to which this undo applies
TABLE_OWNER      VARCHAR2(32)   Y                owner of table to which this undo applies
ROW_ID           VARCHAR2(19)   Y                rowid to which this undo applies
UNDO_SQL         VARCHAR2(4000) Y                SQL corresponding to this undo

该视图的定义为:

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的查询非常耗时
测试一下对于x$ktuqqry表的查询

SQL> select count(addr) from x$ktuqqry;

COUNT(ADDR)
-----------
      74786

如果需要撤消xid=0300150096010000的事务,可以通过如下步骤进行:

SQL> set autotrace on
SQL> select undo_sql from flashback_transaction_query where xid='0300150096010000';

UNDO_SQL
--------------------------------------------------------------------------------
delete from "SYS"."TEST" where ROWID = 'AAAM3VAABAAAO9KAAd';



Execution Plan
----------------------------------------------------------
Plan hash value: 1115820779

------------------------------------------------------------------------------
| Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |           |     1 |  2008 |     0   (0)| 00:00:01 |
|*  1 |  FIXED TABLE FULL| X$KTUQQRY |     1 |  2008 |     0   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(RAWTOHEX("XID")='0300150096010000')


Statistics
----------------------------------------------------------
      90926  recursive calls
          0  db block gets
     238964  consistent gets
      21783  physical reads
          0  redo size
        506  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
       4115  sorts (memory)
          0  sorts (disk)
          2  rows processed

通过执行相应的undo语句可以撤消该事务,通过这些新特性,oracle提供了一种”回滚”提交事务的
方法,极大地方便了用户应对不同情况的数据库恢复.

Leave a Reply

Your email address will not be published.

Proudly powered by WordPress | Indrajeet by Sus Hill.