模拟enq: TX – allocate ITL entry等待

联系:手机/微信(+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不会发生改变.另外可以考虑修改业务逻辑,减少频繁访问

One thought on “模拟enq: TX – allocate ITL entry等待

  1. 飞总,看过您这篇文章,有两个问题没明白:
    1.ITL使用的空间会占用数据块的行数据区吗?
    2.“有3个dml操作成功,即占用了3个itl,所以该block的剩余空间只有38-24=14 byte<24byte”,为什么是减24byte,3个 DML操作ITL占用的总空间不应该是3*24=72吗?

  2. 飞总,看过您这篇文章,有两个问题没明白:
    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)

发表评论

邮箱地址不会被公开。 必填项已用*标注

2 × 4 =