承接《Oracle10g版本后enq: TX – allocate ITL entry等待事件的根源以及解决思路》
由于itl争用主要是initrans不足(10g后今本不受此影响maxtrans失效),块空间不足原因引起,但是特殊的情况下的索引递归事务引起的itl争用的识别也是需要掌握的技术,虽然大量的递归情况较少见,但如何区分相比前面的2种情况就相对复杂点。主要的思路是根据索引块的itl信息来识别,因为上一篇中讲到在索引的枝节点上,有且只有一个ITL slot,它是用于当发生节点分裂的递归事务(Recursive Transaction)。在叶子节点上,第一条ITL Slot也是用于分裂的递归事务的。只要根据相关索引块的负责递归事务的itl事务槽的使用情况就可以判断争用的情况。
思路如下:
1.找出被阻塞的事务
2.根据阻塞的事务找到相关的回滚块以及相关事务起始回滚编号
3.根据回滚块的内容识别相关的索引块
4.dump出相关的索引块识别对应的itl争用情况
例子:
1.测试阻塞
session 1 更新61080块的100行
SQL> update luda set a=a 2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=61080 3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=100; 1 row updated. commit;
session 2 更新61080块的200行
SQL> update luda set a=a 2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=61080 3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=200; 1 row updated. commit;
session 3 更新61080块的300行
SQL> update luda set a=a 2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=61080 3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=300; 1 row updated.
session 4 更新61080块的400行
SQL> update luda set a=a 2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=61080 3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=400; 1 row updated.
session 5 更新61080块的500行hang住
2.找出被阻塞的事务以及相关回滚段信息
确认itl阻塞:
SQL> select s.sid, s.event, s.row_wait_obj# 2 from v$session s where s.sid=151; SID EVENT ROW_WAIT_OBJ# ---------- ------------------------------ ------------- 148 enq: TX - allocate ITL entry -1
确认对应的阻塞事务的回滚相关信息,可以发现阻塞事务对应的回滚在2号数据文件的2109数据块中,起始的回滚记录是0x2e(46的16进制)
SQL> select l.sid req_session, s.sid lock_session, l.lmode, l.request, t.xidusn, t.xidslot, t.start_ubafil, t.start_ubablk, t.start_ubarec 2 from v$lock l, v$transaction t, v$session s 3 where l.type = 'TX' 4 and trunc(id1/power(2,16)) = t.xidusn 5 and l.id2 = t.xidsqn 6 and id1 - power(2,16)*trunc(id1/power(2,16)) = t.xidslot 7 and t.addr = s.taddr 8 and l.request = 4; REQ_SESSION LOCK_SESSION LMODE REQUEST XIDUSN XIDSLOT START_UBAFIL START_UBABLK START_UBAREC ----------- ------------ ---------- ---------- ---------- ---------- ------------ ------------ ------------ 148 159 0 4 5 26 2 2109 46
dump出2号数据文件的2109号数据块
SQL> alter system dump datafile 2 block 2109; System altered.
确认相关对象的object_id
SQL> select object_name,object_id,data_object_id from dba_objects where object_name in ('LUDA','IDX_TEST') and owner='SYS'; OBJECT_NAME OBJECT_ID DATA_OBJECT_ID ---------------------------------------- ---------- -------------- IDX_TEST 51980 51980 LUDA 51978 51978
分析2号数据文件的2109号数据块dump文件,从Rec #0x2e部分开始到结束只有0x2e此条与对象号51980,51978相关回滚记录
*----------------------------- * Rec #0x2e slt: 0x1a objn: 51978(0x0000cb0a) objd: 51978 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: 0x0080083d.014b.2d ctl max scn: 0x0000.000bb362 prv tx scn: 0x0000.000bb37b txn start scn: scn: 0x0000.000bcdc1 logon user: 0 prev brb: 8388917 prev bcl: 0 KDO undo record: KTB Redo op: 0x04 ver: 0x01 op: L itl: xid: 0x0002.010.0000013b uba: 0x00800051.0100.3c flg: C--- lkc: 0 scn: 0x0000.000bcd90 KDO Op code: URP row dependencies Disabled xtype: XAxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x0040ee98 hdba: 0x0040ee91 itli: 1 ispac: 0 maxfr: 4863 tabn: 0 slot: 400(0x190) flag: 0x2c lock: 0 ckix: 71 ncol: 1 nnew: 1 size: 0 Vector content: col 0: [ 3] c2 31 06 End dump data blocks tsn: 1 file#: 2 minblk 2109 maxblk 2109
从bdba地址分析可以获得当前更新对象对luda,前面更新提交的1条语句的部分就是luda的61080号块。
SQL> select dbms_utility.data_block_address_file(TO_NUMBER('0040ee98', 'XXXXXXXX')) file_id, 2 dbms_utility.data_block_address_block(TO_NUMBER('0040ee98', 'XXXXXXXX')) block_id from dual; FILE_ID BLOCK_ID ---------- ---------- 1 61080
在回滚信息中没有发现索引块类型,事务对象只有objno为51978的luda表,类似的索引对象也是用此方法分析。