暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

浅析enq: TX - allocate ITL entry等待事件与ITL事务槽

原创 王君慧 2020-10-01
3912

在分析 enq: TX - allocate ITL entry 这个等待事件之前,首先需要理解什么是ITL事务槽(Interested Transaction List)。

我们知道Oracle的最小的数据存储单位是块(block),ITL事务槽就是位于块头的一部分,它的作用是记录该数据块所发生的事务,一个被使用的ITL事务槽对应当前数据块的一条事务,ITL事务槽的初始数量由initrans参数控制(最小值为1,但实际默认分配两个ITL事务槽),最大数量由maxtrans参数控制(Oracle 10g及以上版本此参数固定为255,不可变更),当事务提交时事务槽可以被重用,我们可以通过dump一个数据块来观察它的结构:
创建测试表插入数据

SQL> create table t1(id number,text varchar2(200));
Table created.
SQL> insert into t1 values(1,'example');
1 row created.
SQL> commit;
Commit complete.
SQL> alter system checkpoint;
System altered.

查看当前表使用的块编号,dump这个数据块

SQL> select id, dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block# from t1;
	ID	FILE#	  BLOCK#
---------- ---------- ----------
	 1	    7	   22965
SQL> alter system dump datafile 7 block 22965;
System altered.

查询生成的trc文件

select i.instance_name||'_ora_' || p.spid|| '.trc' TRACE_NAME from v$session s,v$process p ,v$instance i where s.paddr=p.addr and s.sid in (select userenv('sid') from dual);
TRACE_NAME
--------------------------------------------------------------------------------
orcl_ora_1784.trc

此时可以在数据块的头部发现ITL事务槽的结构如下

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0003.01f.00000567  0x010016ae.0180.01  --U-    1  fsc 0x0000.002f470e
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

可以发现不添加任何参数建表时,其ITL事务槽默认有两个,也就是不论initrans参数是1或者是2,一个BLOCK的事务槽数量至少为2。观察其构成,XID对应回滚段中对应的事务xid,Uba对应回滚段地址,flag对应当前的事务状态,以及最后的事务SCN。

那什么原因会导致enq: TX - allocate ITL entry等待事件呢?

   INST_ID USERNAME         SID    SERIAL#  BLOCKING_INSTANCE BLOCKING_SESSION SQL_ID                     EVENT                   		H
---------- ---------- ---------- ---------- ----------------- ---------------- -------------------------- ------------------------------ ----------
     1 		SYS        278      14642                       		3gbaumsjw3zjg             SQL*Net message to client           0
     1 		TEST       48       17664            1          45 		4vugq1rx8zthc             enq: TX - allocate ITL entry        .04

对于ITL事务槽来说,除去其初始分配的事务槽(可以理解为固定存在的事务槽),在一个BLOCK写满的情况下,继续扩展ITL事务槽需要占用PCTFREE参数指定的预留空间。例如PCTFREE值设定为10%,而一个块的大小是8KB也就是8192B,则预留的空间约为819.2B,而一个ITL事务槽的大小为24B(ITL事务槽大小参考文献,最开始查看一些文章有说大小是46B的,但是实际测试不相符),由此我们可以大致推断其最多可扩展的ITL事务槽数量。而在实际生产环境中,update语句更新该数据块中的字段,使其字段长度增加,也会占用PCTFREE预留空间,导致ITL事务槽的可扩展数量减少。

从根本上来说enq: TX - allocate ITL entry等待事件的产生是由于当前BLOCK没有足够的空间去扩展事务槽,或者由于多个长事务导致的ITL事务槽长时间占用,从而引起事务槽争用,那么解决方法也十分明了:

  1. 修改PCTFREE值预留更多的空间
  2. 修改initrans参数预置一定数量的事务槽
  3. 修改业务语句,减少长事务

需要注意的是1.2两种方法若是在已创建完成的表中,只会对修改参数后新生成的BLOCK有效,若想更改之前的BLOCK需要MOVE TABLE等操作。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论