ITL: Interested Transaction List,也叫事务槽,它位于BLOCK Header。先dump 一个block,看一下这个ITL的信息。
block中也会记录SCN的信息,每个ITL对应一个SCN,由于一个事物的操作可能会涉及到多个BLOCK的更改,所以一个事物可能在多个BLOCK中产生ITL信息。
一般来说,SCN 会保存在4个地方,控制文件中有三个,还有一个在datafile header.
-- dump该数据块
SYS@anqing2(rac2)> alter system dump datafile 1 block 73546;
--使用oradebug查看当前trace文件位置
SYS@anqing2(rac2)> oradebug setmypid
SYS@anqing2(rac2)>oradebug tracefile_name
在trace文件里找到我们的ITL:
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000e.02a.0000026f 0x01400117.0066.0c ---- 1 fsc 0x0001.00000000
0x02 0x000b.007.00000276 0x014000e8.005c.14 C--- 0 scn 0x0000.004fcd83
因为我们执行了一条update操作,并且没有commit,那么这里的lock为1,即Lck值为1.即对应我们ITL值为0x01的记录。
SYS@anqing2(rac2)> select xidusn,xidslot,xidsqn,ubafil,ubablk,ubasqn,ubarec from v$transaction;
xidusn xidslot xidsqn ubafil ubablk ubasqn ubarec
---------- ---------- ---------- ---------- ---------- ---------- ----------
14 42 623 5 279 102 12
2.2验证XID
ITL中的XID的格式为: usn#.slot#.wrap#
我们找到ITL为0X011中的XID=0x000e.02a.0000026f
SYS@anqing2(rac2)>select to_number('000e','XXXXX') from dual;
TO_NUMBER('000E','XXXXX')
-------------------------
14
SYS@anqing2(rac2)>select to_number('02a','XXXXX')from dual;
TO_NUMBER('02A','XXXXX')
------------------------
42
SYS@anqing2(rac2)>select to_number('0000026f','XXXXXXXXX')from dual;
TO_NUMBER('0000026F','XXXXXXXXX')
---------------------------------
623
SYS@anqing2(rac2)>
这个和V$TRANSACTION中记录的XIDUSN,XIDSLOT,XIDSQN相同。
2.3验证uba
UBA的格式为:DBA.seq#.rec#
ITL 为0x01 记录中的UBA=0x01400117.0066.0c,其中01400117 表示的DBA(Data Block Address)的地址。
有关DBA 的内容,参考我的Blog:
Oracle rdba和 dba说明
http://blog.csdn.net/tianlesoftware/archive/2011/06/07/6529346.aspx
将DBA解析成file_id 和 block_id.
SYS@anqing2(rac2)>
select dbms_utility.data_block_address_file(to_number('01400117','xxxxxxxxxxxx'))file_id,dbms_utility.data_block_address_block(to_number('01400117','xxxxxxxxxxxx'))block_id from dual;
FILE_ID BLOCK_ID
---------- ----------
5 279
SYS@anqing2(rac2)> select to_number('0066','xxxx') from dual;
TO_NUMBER('0066','XXXX')
------------------------
102
SYS@anqing2(rac2)> select to_number('0c','xxxx') from dual;
TO_NUMBER('0C','XXXX')
----------------------
12
这个和v$transaction相同。
2.4 dump undo回滚段,找到更改的前镜像
-- dump undo block
SYS@anqing2(rac2)> alter system dump datafile 5 block 279;
System altered.
--get trace file
SYS@anqing2(rac2)> oradebug setmypid
Statement processed.
SYS@anqing2(rac2)> oradebug tracefile_name
/u01/app/oracle/admin/anqing/udump/anqing2_ora_32547.trc
在dump文件中找到xid为 0x000e.02a.0000026f 的记录。
小技巧:
这个文件很大,查找很麻烦,我们可以使用vi的查找功能来实现。
(1)vi /u01/app/oracle/admin/anqing/udump/anqing2_ora_32547.trc
(2)输入:/0x000e.02a.0000026f
(3)如果只有一条记录,一次就能匹配到,如果有多条记录,我们按字母n,查找下一条,知道找到结果位置。
查找的信息如下:
UNDO BLK:
xid: 0x000e.02a.0000026f seq: 0x66 cnt: 0xc irb: 0xc icl: 0x0 flg: 0x0000
该数据块的uba =0x01400117.0066.0c,UBA的格式:DBA.seq#.rec#。这里的cnt对应uba中的rec#。根据这个cnt 序列号号,我们来查找对应的具体内容。方法和上面的一样,在vi中搜索: Rec #0xc, 搜到结果如下:
*-----------------------------
* Rec #0xc slt: 0x2a objn: 54770(0x0000d5f2) objd: 54770 tblspc: 0(0x00000000)
* Layer: 11 (Row) opc: 1 rci 0x0b
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: 0x01400117.0066.0a
KDO Op code: ORP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x00411f4a hdba: 0x00411f49
itli: 1 ispac: 0 maxfr: 4863
tabn: 0 slot: 87(0x57) size/delt: 10
fb: --H-FL-- lb: 0x1 cc: 2
null: --
col 0: [ 2] c1 59
col 1: [ 3] 44 42 41
SYS@anqing2(rac2)> set serveroutput on
SYS@anqing2(rac2)> declare n number;
2 begin
3 dbms_stats.convert_raw_value('c159',n);
4 dbms_output.put_line(n);
5 end;
6 /
88 --输出结果为88,我们修改之前的记录
PL/SQL procedure successfully completed.
通过这个测试,清楚了Oracle通过ITL 找到数据的前镜像了。
三. ITL 与defered Clean(延时块清除)
A "deferred (CURRENT)" cleanout occurs when a DML statement wants to modify the contents of a block and all the available ITLs are showing recent commit cleanouts.The process cleans out the block (incrementing the statistic once) and then uses the ITL slot with the lowest commit SCN.
For example if there are some ITL slots available for use (empty, or showing older, cleaned commits) but the process wants to modify a row that is still marked as locked by a commit cleanout (which don't clear lock bytes), then the process does a full cleanout (again incrementing the statistic) to get the row's lock byte cleared. It won't use the newly cleaned ITL, though if there are more appropriate ITLs (lower commit SCN) available in the block.
在块清除过程中,如果一个块已被修改,下一个会话访问这个块时,可能必须查看最后一个修改这个块的事务是否还是活动的。一旦确定该事务不再活动,就会完成块清除,这样另一个会话访问这个块时就不必再历经同样的过程。
要完成块清除,Oracle会从块首部确定前一个事务所用的undo段(ITL),然后确定从undo首部能不能看出这个块是否已经提交。
可以用以下两种方式完成这种确认:
一种方式是Oracle可以确定这个事务很久以前就已经提交,它在undo段事务表中的事务槽已经被覆盖。
另一种情况是COMMIT SCN还在undo段的事务表中,这说明事务只是稍早前刚提交,其事务槽尚未被覆盖。
当满足以下条件时,就会从defered clean 收到ORA-01555的错误:
首先做了一个修改并COMMIT,块没有自动清理(即没有自动完成“提交清除”,例如修改了太多的块,在SGA块缓冲区缓存的10%中放不下)。
其他会话没有接触这些块,而且在我们这个“倒霉”的查询(稍后显示)命中这些块之前,任何会话都不会接触它们。
开始一个长时间运行的查询。这个查询最后会读其中的一些块。这个查询从SCN t1开始,这就是读一致SCN,必须将数据回滚到这一点来得到读一致性。
开始查询时,上述修改事务的事务条目还在undo段的事务表中。查询期间,系统中执行了多个提交。执行事务没有接触执行已修改的块(如果确实接触到,也就不存在问题了)。
由于出现了大量的COMMIT,undo段中的事务表要回绕并重用事务槽(ITL)。最重要的是,将循环地重用原来修改事务的事务条目。另外,系统重用了undo段的区段,以避免对undo段首部块本身的一致读。
此外,由于提交太多,undo段中记录的最低SCN现在超过了t1(高于查询的读一致SCN)。如果查询到达某个块,而这个块在查询开始之前已经修改并提交,就会遇到麻烦。正常情况下,会回到块所指的undo段,找到修改了这个块的事务的状态(换句话说,它会找到事务的COMMIT SCN)。
如果这个COMMIT SCN小于t1,查询就可以使用这个块。如果该事务的COMMIT SCN大于t1,查询就必须回滚这个块。不过,问题是,在这种特殊的情况下,查询无法确定块的COMMIT SCN 是大于还是小于t1。相应地,不清楚查询能否使用这个块映像。这就导致了ORA-01555错误。
大批量的UPDATE或INSERT会导致块清除(block cleanout),所以在大批量UPDATE或大量加载之后使用DBMS_STATS收集相关对象的统计信息,加载之后完成这些对象的清理。
有关快照过旧的更多内容,参考:
Oracle ORA-01555快照过旧说明
http://blog.csdn.net/tianlesoftware/archive/2009/10/30/4745898.aspx
四. ITL 信息的相关说明
4.1 ITL 中SCN 和 FSC 的区别
Block的cache header部分,记录着一个block scn,它是当前块最后一次变更的时间戳(确切说,这个更新并不是指itl上的scn的最新更新,在接下来delayed block cleanout下的slot重用情况下,可以看到blockscn并不等于itl上的最后一次更新的scn)。可以通过dump获得block scn/last itl scn 和发布ora_rowscn语句获得last itl scn。
发布transaction后,未提交之前,block scn是不会改变的,对应的itl中也并不做scn记录。Block scn的改变,确切的说不是在发布commit之时(因为有delayed block cleanout的情况存在),而是在transaction对应的itl获得commit scn之时。
当发生fast commit cleanout,系统将transaction提交时刻的scn作为commit scn,更新block上 itl和undo segment header的Transaction table的slot上的 scn,并修改block scn,三者是一致的。
发生delayed block cleanout的时候,之前的transaction commit更新的只是Transaction table,而并未做block上的处理,等待下次使用此block的时候,更新block scn和itl状态。block scn和itl的更新又分2种情况:
(1)当不产生slot重用的时候(ITL不重用), delayed block cleanout时,根据Transaction table里面的信息,更新block scn和itl上的Scn/Fsc为transaction曾经提交时候的scn。
(2)当产生slot重用的时候(重用ITL),更新对应itl上scn为control scn,而block scn 为delayed block cleanout发生时刻的scn。
dump block的ITL 的信息如下:
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000e.007.00000236 0x00000000.0000.00C-U- 0 scn 0x0000.005b1f7f
0x02 0x000c.005.000003b4 0x01401727.0144.13C--- 0 scn 0x0000.005bbf0b
0x03 0x0011.007.00000406 0x0140015b.00c7.57--U- 483 fsc 0x0000.005bdee1
这里的SCN和FSC其实就是这个ITL对应的事务提交时候的SCN,那么这里所有槽位上的最大的一个SCN号就表示这个BLOCK最后被更新的时候的SCN。每一个事务对应一个itl 记录。如果该事务没有涉及延时块清除,那么显示的FSC。 如果是延时块清除(delayed block cleanout),那么显示的就是SCN。
4.2 ITL 状态说明
在ITL信息中有一个显示的Flag的状态,FLAG在block中占用1个字节大小。 不同flag 标记的意义如下:
---- = transaction is active, or committedpending cleanout
C--- = transaction has been committed andlocks cleaned out
-B-- = this undo record contains the undofor this ITL entry
--U- = transaction committed (maybe longago); SCN is an upper bound
---T = transaction wasstill active at block cleanout SCN
最后修改时间:2022-05-18 09:56:13
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




