undo机制是oracle的巧妙之处,也是学习oracle的难点之一。
下面我们从内部来具体了解它。
会话1:scott用户,发起一个事务
hr@ORCL> conn scott/oracle
Connected.
scott@ORCL> UPDATE emp SET sal=4000 WHERE empno=7788;
1 row updated.
scott@ORCL> SELECT empno,ename,job,mgr,sal FROM emp WHERE empno=7788;
EMPNO ENAME JOB MGR SAL
---------- ---------- --------- ---------- ----------
7788 SCOTT ANALYST 7566 4000
先不提交这个事务,会话2:SYS用户
获得事务信息
从v$transaction,可得:该事务在9号回滚段,位于26号事务槽
sys@ORCL> SELECT xidusn,xidslot FROM v$transaction;
XIDUSN XIDSLOT
---------- ----------
9 26
从v$rollstat,也可见该事务高就9号回滚段
sys@ORCL> SELECT usn,xacts FROM v$rollstat;
USN XACTS
---------- ----------
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 1
10 0
dump回滚段的段头信息
sys@ORCL> SELECT * FROM v$rollname a WHERE a.usn=9;
USN NAME
---------- ------------------------------
9 _SYSSMU9$
sys@ORCL> alter system dump undo header '_SYSSMU9$';
System altered.
sys@ORCL> select spid from v$process where addr in (select paddr from v$session where sid in (select sid
2 from v$mystat where rownum=1));
SPID
------------
10086
部分内容摘入如下:
********************************************************************************
Undo Segment: _SYSSMU9$ (9)
********************************************************************************
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 4 #blocks: 31
last map 0x00000000 #maps: 0 offset: 4080
Highwater:: 0x00800615 ext#: 2 blk#: 4 ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 2
Unlocked
Map Header:: next 0x00000000 #extents: 4 obj#: 0 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x0080008a length: 7
0x008000d9 length: 8
0x00800611 length: 8
0x00800669 length: 8
Retention Table
-----------------------------------------------------------
Extent Number:0 Commit Time: 1344269736
Extent Number:1 Commit Time: 1344276385
Extent Number:2 Commit Time: 1344264118
Extent Number:3 Commit Time: 1344264252
TRN CTL:: seq: 0x0105 chd: 0x0019 ctl: 0x0014 inc: 0x00000000 nfb: 0x0000
mgc: 0x8201 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)
uba: 0x00800615.0105.11 scn: 0x0000.000d2615
Version: 0x01
FREE BLOCK POOL::
uba: 0x00000000.0105.10 ext: 0x2 spc: 0x16f6
uba: 0x00000000.0105.03 ext: 0x2 spc: 0x1eac
uba: 0x00000000.0101.0b ext: 0xb spc: 0x198c
uba: 0x00000000.0000.00 ext: 0x0 spc: 0x0
uba: 0x00000000.0000.00 ext: 0x0 spc: 0x0
TRN TBL::
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
------------------------------------------------------------------------------------------------
0x00 9 0x00 0x0162 0x0029 0x0000.000d2ab9 0x00800613 0x0000.000.00000000 0x00000001 0x00000000 1344280244
............................................
0x1a 10 0x80 0x0162 0x0002 0x0000.00000000 0x00800615 0x0000.000.00000000 0x00000001 0x00000000 0
............................................
这就是神秘的回滚段头的信息,其中包括事务表信息。其中,0x1a是个16进制数,转成10进制:
scott@ORCL> select to_number('1a','xx') from dual;
TO_NUMBER('1A','XX')
--------------------
26
由此,可知:0x1a为26.回顾前面的事务信息,该事务正好占用的是第26号事务槽,状态(state)为10代表的是活动事务。
dump旧值信息
段头信息的第七列:dba(data block address),指的就是回滚块的地址0x00800615
下面把dba翻译一下
sys@ORCL> select to_number('00800615','xxxxxxxx') from dual;
TO_NUMBER('00800615','XXXXXXXX')
--------------------------------
8390165
sys@ORCL> select dbms_utility.data_block_address_file(8390165) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(8390165)
---------------------------------------------
2
sys@ORCL> select dbms_utility.data_block_address_block(8390165) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(8390165)
----------------------------------------------
1557
由此,可知:旧值在2号文件的第1557个回滚块上
这与从v$transaction查询得到的数据完全一致:
sys@ORCL> select ubafil,ubablk from v$transaction;
UBAFIL UBABLK
---------- ----------
2 1557
回到会话1,继续DML事务:scott用户
scott@ORCL> update emp set sal=4000 where empno=7788;
1 row updated.
scott@ORCL> update emp set sal=4000 where empno=7782;
1 row updated.
scott@ORCL> update emp set sal=40000 where empno=7698;
1 row updated.
会话2:sys用户
把回滚块1557dump出来
sys@ORCL> select spid from v$process where addr in (select paddr from v$session where sid in (select sid from v$mystat where rownum=1));
SPID
------------
11146
sys@ORCL> alter system dump datafile 2 block 1557;
System altered.
回滚块1557里面开头的信息部分如下:
*** 2012-08-07 16:31:42.449
*** SERVICE NAME:(SYS$USERS) 2012-08-07 16:31:42.355
*** SESSION ID:(135.102) 2012-08-07 16:31:42.355
Start dump data blocks tsn: 1 file#: 2 minblk 1557 maxblk 1557
buffer tsn: 1 rdba: 0x00800615 (2/1557)
scn: 0x0000.000d36d2 seq: 0x01 flg: 0x04 tail: 0x36d20201
frmt: 0x02 chkval: 0xbeca type: 0x02=KTU UNDO BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0E7E4400 to 0x0E7E6400
......................
********************************************************************************
UNDO BLK:
xid: 0x0009.01a.00000162 seq: 0x105 cnt: 0x14 irb: 0x14 icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f08 0x02 0x1e58 0x03 0x1df4 0x04 0x1da0 0x05 0x1d1c
0x06 0x1ca0 0x07 0x1c54 0x08 0x1b80 0x09 0x1afc 0x0a 0x1a70
0x0b 0x198c 0x0c 0x1924 0x0d 0x18cc 0x0e 0x17e8 0x0f 0x1780
0x10 0x1728 0x11 0x16a8 0x12 0x1650 0x13 0x15f4 0x14 0x1598
*-----------------------------
注意,这部分信息有个参数irb: 0x14。irb指的是回滚段中记录的最近所有未提交的事务的开始之处,也就是最近一次被修改的地方,如果要回滚,这便是回滚的起点。
由上,可知:(irb: 0x14)的偏移地址为0x1598
找到irb:0x14信息,如下:
*-----------------------------
* Rec #0x14 slt: 0x1a objn: 51148(0x0000c7cc) objd: 51148 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x13
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x00800615.0105.13
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x01000020 hdba: 0x0100001b
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 5(0x5) flag: 0x2c lock: 0 ckix: 191
ncol: 8 nnew: 1 size: 1
col 5: [ 3] c2 1d 33
c2 1d 33转换为10进制就是2850.这是最后被更新的记录的旧值。也就是update emp set sal=4000 where empno=7698。
注意,这里有几个参数需要关注:
1)参数rci 0x13,该参数代表的就是undo chain(同一个事务中的多次修改,根据chain链接关联),此处的rci 0x13指向第二次修改update emp set sal=4000 where empno=7782.此时,如果有其他进程查询scott.emp表,则oracle需要构造一致性读来把数据展现给用户。
2)参数bdba: 0x01000020,该参数代表旧值对应的数据块的地址,下面把这个参数翻译出来:
scott@ORCL> select to_number('01000020','xxxxxxxx') from dual;
TO_NUMBER('01000020','XXXXXXXX')
--------------------------------
16777248
scott@ORCL> select dbms_utility.data_block_address_file(16777248) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16777248)
----------------------------------------------
4
scott@ORCL> select dbms_utility.data_block_address_block(16777248) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16777248)
-----------------------------------------------
32
再将4号文件的第32个块dump出来:
sys@ORCL> select spid from v$process where addr in (select paddr from v$session
2 where sid in (select sid from v$mystat where rownum=1));
SPID
------------
13929
sys@ORCL> alter system dump datafile 4 block 32;
System altered.
部分内容摘入如下:
Start dump data blocks tsn: 4 file#: 4 minblk 32 maxblk 32
buffer tsn: 4 rdba: 0x01000020 (4/32)
scn: 0x0000.000d36d2 seq: 0x01 flg: 0x04 tail: 0x36d20601
frmt: 0x02 chkval: 0xa9ea type: 0x06=trans data
Block header dump: 0x01000020
Object id on Block? Y
seg/obj: 0xc7cc csc: 0x00.b9cf3 itc: 2 flg: E typ: 1 - DATA
brn: 0 bdba: 0x1000019 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0003.011.000000f2 0x00805794.00c8.49 C--- 0 scn 0x0000.0006bfdb
0x02 0x0009.01a.00000162 0x00800615.0105.14 ---- 3 fsc 0x0002.00000000
这里存在ITL事务槽信息,事务必须得到一个ITL事务槽才能够进行数据修改。ITL内容主要包括xid(指向回滚段头的ITL)、uba(指向回滚块)、Lck(行头锁的个数,此处修改三次,故有3个锁)。在以上输出中,可知:itl2(0x02)上存在活动事务。
将xid(0x0009.01a.00000162)分解一下:0009表明该事务指向9号回滚段,01a表明该事务指向26号事务槽,00000162表明该事务第354次被覆盖(因为回滚段是循环使用的)。
将uba(0x00800615.0105.14)分解一下:00800615表明第1557个回滚块,14是irb信息(回滚的起点)。
至此,undo段和数据块里面的事务信息被完全解析出来,二者完全一致!
分享到:
相关推荐
oracle回滚段使用率过高之解决方法 推荐针对不同的情况有多种解决.
回滚段探究 在eygle转 在网上看到的,感觉写的不错.... 大家一起学习,如果侵犯了作者版权,请联系本人将删除
回滚段管理一直是ORACLE数据库管理的一个难题,本文通过实例介绍ORACLE回滚段的概念
回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值)。回滚段的头部包含正在使用的该回滚段事务的信息。一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段可以存放多个事务的回滚信息。
对于回滚段出现异常,无法启动数据库的处理脚本
oracle 事务 回滚 存储过程 自用
对Oracle数据库回滚日志的清理,删除不必要的日志文件。
Oracle回滚段管理知识.pptx
回滚段是数据库的一部分,它记录数据库变更的信息。使用这些信息实现数据库的读一致性及其恢复。若回滚段出现故障,则数据库不能正常启动,导致数据库瘫痪,...本文将为大家介绍Oracle回滚表空间数据文件误删除处理。
正在看的ORACLE教程是:Oracle回滚段的概念,用法和规划及问题的解决。回滚段管理一直是ORACLE数据库管理的一个难题,本文通过实例介绍ORACLE回滚段的概念,用法和规划及问题的解决。 回滚段概述 回滚段用于存放...
Oracle数据库回滚段的故障分析与性能优化.pdf
以前总是搞不清清楚回滚段的问题,最近找到这样一个非常好的文档来和大家分享。
对undo 回滚段的理解对于后期数据库的数据恢复有很大的作用,dba必学!
当在 Oracle Database 10g 中回滚长期运行的事务时,无论是并行实例恢复会话还是用户执行的回滚语句,您所需做的一切就是查看视图 V$SESSION_LONGOPS 并评估还需要多少...本文对Oracle数据库中回滚监视进行深入探讨。
主要介绍了Oracle回滚段使用查询代码详解的相关资料,需要的朋友可以参考下
回滚段的作用 * 回滚段的类型 * 回滚段的数量、大小及存储参数 * 回滚段的维护及查询 * 有关回滚段的常见错误及解决方法
oracle 回滚段参数的管理,特别是orale 8i版本前的应用。
主要是在实际开发中运用到对数据库的操作同步进行,几个操作相关性的问题。 回滚了就说明事务有个判断,阻止SQL的自动提交,添加认为控制