联系:手机/微信(+86 17813235971) QQ(107644445)
标题:模拟enq: TX – allocate ITL entry等待
作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]
今天在分析一份awr中发现了较为明显的enq: TX – allocate ITL entry等待,这里通过试验详细重现了enq: TX – allocate ITL entry等待
创建测试对象
SQL> create table t_xifenfei (name char(2000)) pctfree 0 initrans 1; Table created. SQL> insert into t_xifenfei select object_name from all_objects where rownum < 5; 4 rows created. SQL> commit; Commit complete. SQL> alter system flush buffer_cache; System altered. SQL> select distinct dbms_rowid.rowid_relative_fno(rowid) file#, 2 dbms_rowid.rowid_block_number(rowid) block# from t_xifenfei; FILE# BLOCK# ---------- ---------- 4 32
bbed查看block
BBED> set block 32 BLOCK# 32 BBED> map File: /u01/oracle/oradata/XFF/users01.dbf (0) Block: 32 Dba:0x00000000 ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 struct ktbbh, 72 bytes @20 struct kdbh, 14 bytes @100 struct kdbt[1], 4 bytes @114 sb2 kdbr[4] @118 ub1 freespace[38] @126 --该block空闲空间为38byte ub1 rowdata[8024] @164 ub4 tailchk @8188 BBED> p ktbbh struct ktbbh, 72 bytes @20 ub1 ktbbhtyp @20 0x01 (KDDBTDATA) union ktbbhsid, 4 bytes @24 ub4 ktbbhsg1 @24 0x0000d318 ub4 ktbbhod1 @24 0x0000d318 struct ktbbhcsc, 8 bytes @28 ub4 kscnbas @28 0xc0320e3b ub2 kscnwrp @32 0x0b2c b2 ktbbhict @36 2 ub1 ktbbhflg @38 0x32 (NONE) ub1 ktbbhfsl @39 0x00 ub4 ktbbhfnx @40 0x01000019 struct ktbbhitl[0], 24 bytes @44 --1个itl slot为24byte struct ktbitxid, 8 bytes @44 ub2 kxidusn @44 0x0015 ub2 kxidslt @46 0x0019 ub4 kxidsqn @48 0x00000005 struct ktbituba, 8 bytes @52 ub4 kubadba @52 0x0080009d ub2 kubaseq @56 0x0002 ub1 kubarec @58 0x28 ub2 ktbitflg @60 0x2004 (KTBFUPB) union _ktbitun, 2 bytes @62 b2 _ktbitfsc @62 0 ub2 _ktbitwrp @62 0x0000 ub4 ktbitbas @64 0xc0320e4e struct ktbbhitl[1], 24 bytes @68 --有两个itl slot struct ktbitxid, 8 bytes @68 ub2 kxidusn @68 0x0000 ub2 kxidslt @70 0x0000 ub4 kxidsqn @72 0x00000000 struct ktbituba, 8 bytes @76 ub4 kubadba @76 0x00000000 ub2 kubaseq @80 0x0000 ub1 kubarec @82 0x00 ub2 ktbitflg @84 0x0000 (NONE) union _ktbitun, 2 bytes @86 b2 _ktbitfsc @86 0 ub2 _ktbitwrp @86 0x0000 ub4 ktbitbas @88 0x00000000
通过bbed我们可以得出如下结论:
1.该block剩余38 byte 空闲空间可以用来存放数据
2.该block 初始化 itl 为2(和我们设置的1不相符)
3.一个itl slot为24byte
更新表记录
--session 1 SQL> select trim(name) from t_xifenfei; TRIM(NAME) -------------------------------------------------------------------------------- ICOL$ I_USER1 CON$ UNDO$ SQL> update t_xifenfei set name='WWW.XIFENFEI.COM' WHERE name='ICOL$'; 1 row updated. --session 2 SQL> update t_xifenfei set name='www.orasos.com' where name='UNDO$'; 1 row updated. --session 3 SQL> update t_xifenfei set name='www.xifenfei.com' where name='CON$'; 1 row updated. --session 4 SQL> update t_xifenfei set name='www.xifenfei.com' where name='I_USER1'; --hang住 --session 5 SQL> select event from v$session where event like 'enq%'; EVENT ---------------------------------------------------------------- enq: TX - allocate ITL entry
通过这里可以看到我们模拟了4个update 该block操作(均未提交),前面三个可以正常的update操作,第四个出现了enq: TX – allocate ITL entry等待,根据我们知识分析(未提交事务的itl不能覆盖,一个dml操作需要一个itl),这里使用了3个itl slot,而我们已经知道一个itl 需要24byte,该block初始化有2个itl,现在这里有3个dml操作成功,即占用了3个itl,所以该block的剩余空间只有38-24=14 byte<24byte,因此无法分配第四个itl slot从而出现了enq: TX - allocate ITL entry等待
bbed验证上述分析
BBED> map File: /u01/oracle/oradata/XFF/users01.dbf (0) Block: 32 Dba:0x00000000 ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 struct ktbbh, 96 bytes @20 struct kdbh, 14 bytes @124 struct kdbt[1], 4 bytes @138 sb2 kdbr[4] @142 ub1 freespace[14] @150 ub1 rowdata[8024] @164 ub4 tailchk @8188 BBED> p ktbbh struct ktbbh, 96 bytes @20 ub1 ktbbhtyp @20 0x01 (KDDBTDATA) union ktbbhsid, 4 bytes @24 ub4 ktbbhsg1 @24 0x0000d318 ub4 ktbbhod1 @24 0x0000d318 struct ktbbhcsc, 8 bytes @28 ub4 kscnbas @28 0xc0320eb0 ub2 kscnwrp @32 0x0b2c b2 ktbbhict @36 3 ub1 ktbbhflg @38 0x32 (NONE) ub1 ktbbhfsl @39 0x00 ub4 ktbbhfnx @40 0x01000019 struct ktbbhitl[0], 24 bytes @44 struct ktbitxid, 8 bytes @44 ub2 kxidusn @44 0x0003 ub2 kxidslt @46 0x001f ub4 kxidsqn @48 0x00000208 struct ktbituba, 8 bytes @52 ub4 kubadba @52 0x00800027 ub2 kubaseq @56 0x0414 ub1 kubarec @58 0x01 ub2 ktbitflg @60 0x0001 (NONE) union _ktbitun, 2 bytes @62 b2 _ktbitfsc @62 0 ub2 _ktbitwrp @62 0x0000 ub4 ktbitbas @64 0x00000000 struct ktbbhitl[1], 24 bytes @68 struct ktbitxid, 8 bytes @68 ub2 kxidusn @68 0x000a ub2 kxidslt @70 0x000f ub4 kxidsqn @72 0x00000185 struct ktbituba, 8 bytes @76 ub4 kubadba @76 0x0080008a ub2 kubaseq @80 0x01a6 ub1 kubarec @82 0x0c ub2 ktbitflg @84 0x0001 (NONE) union _ktbitun, 2 bytes @86 b2 _ktbitfsc @86 0 ub2 _ktbitwrp @86 0x0000 ub4 ktbitbas @88 0x00000000 struct ktbbhitl[2], 24 bytes @92 struct ktbitxid, 8 bytes @92 ub2 kxidusn @92 0x0008 ub2 kxidslt @94 0x002a ub4 kxidsqn @96 0x00000217 struct ktbituba, 8 bytes @100 ub4 kubadba @100 0x008000cc ub2 kubaseq @104 0x0291 ub1 kubarec @106 0x12 ub2 ktbitflg @108 0x0001 (NONE) union _ktbitun, 2 bytes @110 b2 _ktbitfsc @110 0 ub2 _ktbitwrp @110 0x0000 ub4 ktbitbas @112 0x00000000
可以看到剩余空间为14byte,事务槽为3个,因此上述分析为正确。
提交会话测试
--session 1 SQL> commit; Commit complete. --session 4 SQL> update t_xifenfei set name='www.xifenfei.com' where name='I_USER1'; 1 row updated.
证明commit掉事务后,itl slot可以重利用
总结说明
enq: TX – allocate ITL entry为分配ITL条目的等待,因为PCTFREE不足,BLOCK中没有足够空间分配ITL,ORACLE只能重用ITL,但是这个时候由于没有COMMIT,无法重用ITL,所以会出现allocate ITL等待事件。要解决此类问题,我们可以考虑增加PCTFREE和initrans大小,需要注意该修改只能对于新block生效,已经存放数据的block不会发生改变.另外可以考虑修改业务逻辑,减少频繁访问
飞总,看过您这篇文章,有两个问题没明白:
1.ITL使用的空间会占用数据块的行数据区吗?
2.“有3个dml操作成功,即占用了3个itl,所以该block的剩余空间只有38-24=14 byte<24byte”,为什么是减24byte,3个 DML操作ITL占用的总空间不应该是3*24=72吗?
1. itl和数据是行数据是共用空间的
2. 一个itl 是24,这个数据库只剩下38,因此38-24(第三个dml,itl)=14<24(第四个itl)