[分享]ITL_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 1982 | 回复: 0   主题: [分享]ITL        下一篇 
xiaogang.xu
注册用户
等级:上士
经验:251
发帖:13
精华:0
注册:1970-1-1
状态:离线
发送短消息息给xiaogang.xu 加好友    发送短消息息给xiaogang.xu 发消息
发表于: IP:您无权察看 2016-8-15 17:25:29 | [全部帖] [楼主帖] 楼主

    ITL(Interested Transaction List)是Oracle数据块内部的一个组成部分,用来记录该块所有发生的事务。事务在对数据块中的记录加锁时,需要首先在数据块头部记录下该事务的相关信息,这样一个记录就是一条ITL槽(slot)。ITL TX等待发生在事务请求对数据块中记录加锁时,数据块上没有足够ITL槽。


  导致发生ITL不足的原因有3种:


  1、INITRANS太小,没有保留足够的ITL空间,当数据块被数据记录占满(或接近满)后,数据块上没有足够空间创建新的ITL槽位(尽管数据块上ITL数量没有达到MAXTRANS的限制),这时,新的事务向其申请加锁时,就会发生ITL争用等待。


  注1:尽管有PCTFREE为数据块预留了空间,但是,UPDATE操作可能会将其占用,导致空间不足。


  注2:INITRANS不足的问题不会出现在索引数据块上,当发现没有足够空间分配ITL slot时,无论是枝点块还是叶子块,数据块会发生分裂(Index Block Split)。


  2、MAXTRANS不足。当受到MAXTRANS限制时,也会发生此类等待。MAXTRANS的默认值是255(10g以后则不能修改这一参数),但是其实际大小是受到块的大小的限制的。ITL Slot占用的空间不会超过块大小的50%(实际上,如数据块为2K,则ITL最多为41,4k数据块的ITL最大数为83,8K数据块则为169)。


  3、索引块上的递归事务的ITL slot争用。这一类等待比较特殊。在索引的枝节点上,有且只有一个ITL slot,它是用于当发生节点分裂的递归事务(Recursive Transaction)。在叶子节点上,第一条ITL Slot也是用于分裂的递归事务的。在一个用户事务中,如果发生多次分裂,每一次分裂都是由一个单独的递归事务控制的,如果下层节点分裂导致其父节点分裂,它们的分裂则由同一个递归事务控制。当2个事务同时需要分裂一个枝节点或者叶子节点时,或者枝节点下的2个子节点分别被2个事务分裂,就会造成这种ITL等待。


  解决方法:


  系统中存在少量的ITL等待是正常的,只有当其对系统造成了影响(如awr report中,在top 5 events中发现该事件),或者对应用造成了直接影响(如死锁,再如发现某一会话存在大量等待ITL),我们才需要采取相应手段进行处理。针对导致ITL等待不同原因,我们要采取不同的手段来处理。


  INITRANS不足


  这种情况只会出现的表的数据块上,如我们上述的例子:数据块上的ITL数量并没有达到MAX TRANS的限制,可用空间小于24字节。发生这种情况的表通常会被经常UPDATE,从而造成预留空间(PCTFREE)被填满。如果我们发现这类ITL等待对系统已经造成影响,可以通过增加表的INITRANS或者PCTFREE来解决(视该表上的并发事务量而定,通常,如果并发量高,建议优先增加INITRANS,反之,则优先考虑增加PCTFREE)。


  要注意的一点是,如果是使用ALTER TABLE的方式修改这2个参数的话,只会影响新的数据块,而不会改变已有数据的数据块--要做的这一点,需要将数据导出/导入、重建表。


  MAXTRANS不足


  这一情况是由高并发引起的:同一数据块上的事务量已经超出了其实际允许的ITL数(如前所述,ITL slot所占空间不能超过数据块大小的一半,如8K的限制为169)。因此,要解决这类问题就需要从应用着手,减少事务的并发量;长事务,在保证数据完整性的前提下,增加commit的频率,修改为短事务,减少资源占用事件。而对于OLAP系统来说(例如,其存在高并发量的数据录入模块),可以考虑增大数据块大小。


  递归事务ITL争用


  这一类等待通常是系统存在并发事务频繁插入、修改数据导致,其往往伴随"enq: TX - index contention"事件出现。根本解决方法就是要减少索引分裂,如使用大数据块、减少索引中效率低、使用率低的字段等。


ITL等待的例子: 

create table test(a int) pctfree 0 initrans 1; 


我们这里指定pctfree为0,initrans为1,就是为了更观察到itl的真实等待情况,那么,现在,我们个这些块内插入数据,把块填满,让它不能有空间分配。 


begin

  for i in 1 .. 2000 loop

    insert into test values (i);

  end loop;

end;

commit;


我们再检查数据填充的情况: 

select f, b, count(*)

  from (select dbms_rowid.rowid_relative_fno(rowid) f,

               dbms_rowid.rowid_block_number(rowid) b

          from test)

 group by f, b;

         F          B   COUNT(*) 

---------- ---------- ---------- 

         1      29690        734 

         1      29691        734 

         1      29692        532 

可以发现,这2000条数据分布在3个块内部,其中有2个块添满了,一个块是半满的。我们dump一个满的块,可以看到itl信息: 


alter system dump datafile 1 block 29690; 


回到os,在udump目录下,检查跟踪文件,可以看到如下的信息 

    Itl           Xid                  Uba         Flag  Lck        Scn/Fsc 

    0x01   0x0006.002.0000158e  0x0080104d.00a1.6e  --U-  734  fsc 0x0000.6c9deff0 

    0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000 


发现,采用如上参数创建的表,块内部默认有2个itl槽位。 

因为只有2个ITL槽位,我们可以用三个会话来模拟等待: 


会话1,我们更新这个块内部的第一行: 

update test set a = a 

where dbms_rowid.ROWID_BLOCK_NUMBER(rowid) = 29690 and dbms_rowid.ROWID_ROW_NUMBER(rowid) = 1;


会话2,我们更新这个块内部的第2行: 

update test set a = a 

where dbms_rowid.ROWID_BLOCK_NUMBER(rowid) = 29690 and dbms_rowid.ROWID_ROW_NUMBER(rowid) = 2;


会话3(SID=153),我们更新这个块内部的第三行,发现被阻塞: 

update test set a = a 

where dbms_rowid.ROWID_BLOCK_NUMBER(rowid) = 29690 and dbms_rowid.ROWID_ROW_NUMBER(rowid) = 3;


Piner@10gR2>select EVENT from v$session_wait where sid=153 

EVENT 

---------------------------- 

enq: TX - allocate ITL entry 


因为该块只有2个itl槽位,而现在发生了3个事务,而且,因为该块被数据添满,根本没有剩余的空间来分配新的itl,所以发生了等待。如果我们这个实验发生在半满的块29692上面,就发现进程3不会被阻塞,因为这里有足够的空间可以分配新的itl。 





赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论