oracle itl解析,Oracle数据库中ITL详解

1、什么是ITL

ITL(Interested Transaction

List)是Oracle数据块内部的一个组成部分,用来记录该块所有发生的事务,一个itl可以看作是一个记录,在一个时间,可以记录一个事务(包括提交或者未提交事务)。当然,如果这个事务已经提交,那么这个itl的位置就可以被反复使用了,因为itl类似记录,所以,有的时候也叫itl槽位。

如果一个事务一直没有提交,那么,这个事务将一直占用一个itl槽位,itl里面记录了事务信息,回滚段的入口,事务类型等等。如果这个事务已经提交,那么,itl槽位中还保存的有这个事务提交时候的SCN号。如dump一个块,就可以看到itl信息:

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

对于已经提交的事务,itl槽位最好不要马上被覆盖,因为一致性读可能会用到这个信息,一致性读的时候,可能需要从这里获得回滚段的入口,并从回滚段中获得一致性读。

itl的个数,受参数initrans控制,最大的itl个数,受maxtrans控制,在一个块内部,默认分配了2个或3个itl的个数,如果这个块内还有空闲空间,那么Oracle是可以利用这些空闲空间并再分配itl的。如果没有了空闲空间,那么,这个块因为不能分配新的itl,所以就可能发生itl等待。

如果在并发量特别大的系统中,最好分配足够的itl个数,其实它并浪费不了太多的空间,或者,设置足够的pctfree,保证itl能扩展,但是pctfree有可能是被行数据给消耗掉的,如update,所以,也有可能导致块内部的空间不够而导致itl等待。

2、ITL等待

我们看一个ITL等待的例子:

Piner@10gR2>create

table test(a int) pctfree 0 initrans 1;

Table created.

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

Piner@10gR2>begin

2 for i in 1..2000 loop

3 insert into test values(i);

4 end loop;

5 end;

6 /

PL/SQL procedure successfully completed.

Piner@10gR2>commit;

Commit complete.

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

Piner@10gR2>select

f,b,count(*) from (

2 select dbms_rowid.rowid_relative_fno(rowid) f,

3 dbms_rowid.rowid_block_number(rowid) b

4 from test) group by f,b;

F B COUNT(*)

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

1 29690 734

1 29691 734

1 29692 532

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

Piner@10gR2>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槽位,如果这里不指定initrans 1,默认是有3个itl槽位的。

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

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

Piner@10gR2>update

test set a=a

2 where

dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690

3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=1;

1 row updated.

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

Piner@10gR2>update

test set a=a

2 where

dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690

3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=2;

1 row updated.

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

Piner@10gR2>update

test set a=a

2 where

dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690

3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;

可以看到,会话被阻塞

观察这个时候的等待事件,我们可以发现是ITL等待:

Piner@10gR2>select

EVENT from v$session_wait where sid=153

EVENT

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

enq: TX - allocate ITL entry

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

3、ITL死锁

那么,理解了itl的阻塞,我们也就可以分析itl的死锁了,因为有阻塞,一般就能发生死锁。还是以上的表,因为有2个itl槽位,我们需要拿2个满的数据块,4个进程来模拟itl死锁:

会话1

Piner@10gR2>update

test set a=a

2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690

3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值