oracle ITL(事务槽)的理解

1、ITL描述: 并发

ITL(Interested Transaction List)是Oracle数据块内部的一个组成部分,位于数据块头(block header),itl由xid,uba,flag,lck和scn/fsc组成,用来记录该块全部发生的事务,一个itl能够看做是一条事务记录。固然,若是这个事务已经提交,那么这个itl的位置就能够被反复使用了,由于itl相似记录,因此,有的时候也叫itl槽位。若是一个事务一直没有提交,那么,这个事务将一直占用一个itl槽位,itl里面记录了事务信息,回滚段的入口,事务类型等等。若是这个事务已经提交,那么,itl槽位中还保存的有这个事务提交时候的SCN号。 oracle

ITL个数其最小值为1,由参数initrans控制(因为兼容性的缘由,oracle会在对象的存储块分配两个itl,因此initrans的最小值实际上为2),最大值为255,由参数maxtrans控制,最大值参数在10g之后不能被修改,itl是block级的概念,一个itl占用块46B的空间,参数initrans意味着块中除去block header外一部分存储空间没法被记录使用(46B*initrans),当块中还有必定的free space时,oracle可使用free space构建itl供事务使用,若是没有了free space,那么,这个块由于不能分配新的itl,因此就可能发生itl等待。
若是在并发量特别大的系统中,最好分配足够的itl个数,其实它并浪费不了太多的空间,或者,设置足够的pctfree,保证itl能扩展,可是pctfree有多是被行数据给消耗掉的,如update,因此,也有可能致使块内部的空间不够而致使itl等待。 高并发

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
  大数据

Xid:事务id,在回滚段事务表中有一条记录和这个事务对应 this

Uba:回滚段地址,该事务对应的回滚段地址 spa

  第一段地址:回滚数据块的地址,包括回滚段文件号和数据块号 rest

  第二段地址:回滚序列号 对象

  第三段地址:回滚记录号 递归

  SELECT UBAFIL 回滚段文件号,UBABLK 数据块号,UBASQN 回滚序列号,UBAREC 回滚记录号 FROM v$transaction --查看UBA 事件

Flag:事务标志位。这个标志位就记录了这个事务的操做,各个标志的含义分别是:

----- = 事务是活动的,或者在块清除前提交事务

C--- = 事务已经提交而且清除了行锁定。

-B-- = this undo record contains the undo for this ITL entry

--U- = 事务已经提交(SCN已是最大值),可是锁定尚未清除(快速清除)。

---T =当块清除的SCN被记录时,该事务仍然是活动的,块上若是有已经提交的事务,那么在clean ount的时候,块会被进行清除,可是这个块里面的事务不会被清除。

Lck:影响的记录数

Scn/Fsc:快速提交(Fast Commit Fsc)的SCN或者Commit SCN。

每条记录中的行级锁对应于Itl列表中的序号,即哪一个事务在该记录上产生的锁。

  

 2、ITL等待

      发生等待的场景:

     1.超过maxtrans配置的最大ITL数

      2.initrans不足,没有足够的free space来扩展ITL

      解决方法:

      1.maxtrans不足:这一状况是由高并发引发的:同一数据块上的事务量已经超出了其实际容许的ITL数。所以,要解决这类问题就须要从应用着手,减小事务的并发量;长事务,在保证数据完整性的前提下,增长commit的频率,修改成短事务,减小资源占用事件。而对于OLAP系统来讲(例如,其存在高并发量的数据录入模块),能够考虑增大数据块大小。

      2.initrans不足:数据块上的ITL数量并无达到MAX TRANS的限制,发生这种状况的表一般会被常常UPDATE,从而形成预留空间(PCTFREE)被填满。若是咱们发现这类ITL等待对系统已经形成影响,能够经过增长表的INITRANS或者PCTFREE来解决(视该表上的并发事务量而定,一般,若是并发量高,建议优先增长INITRANS,反之,则优先考虑增长PCTFREE)。

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

 

ITL重用后如何实现前ITL读一致性

     ORACLE经过ITL条目中记录的回滚段地址找到回滚段,实现读一致性,若是事务已提交,ITL就能够被重用,可是若前一个ITL被重用,前一个ITL的读一致性是如何实现的呢?

     假定block只有一个itl,假定第一个事务的时候产生了 ITL-0 

     第二个事务来了,产生了 ITL-1 ,ITL-1 里面的UBA 能够找到回滚段地址,回滚段中除了记录了 block用户数据的 before image 外还记录了  ITL-0 的信息。

     第三个事务来了,产生了 ITL-2  , ITL-2 中 UBA 指向回滚段,回滚段中 也记录了 ITL-1 的信息。

     这样当一个查询若须要ITL-0时候的信息,则找到当前block,发现是 ITL-2 ,根据UBA找到回滚段进行 roll 获得  变化前 block ,这个时候发现block中是 ITL-1 . 还不能知足需求。 因而再根据 ITL-1 中的 UBA 又去回滚段中找到数据来进行roll,获得一个block 数据,这个时候block中就有了 ITL-0。

     经过根据当前ITL进行递归的方式找到数据,实现以前ITL的独一致性。

行锁原理:

Oracle的锁机制是一种轻量级的锁定机制,不是经过构建锁列表来进行数据的锁定管理,而是直接将锁做为数据块的属性,存储在数据块首部。这个是经过ITL来实现的,一个事务要修改块中的数据,必须得到该块中的一个itl(经过initrans预先分配的或者是经过free space构建的)。经过itl和undo segment header中的transaction table,能够知道事务处于活动阶段,仍是已经完成。事务在修改块时(其实就是在修改行)会检查行中row header中的标志位,若是该标志位为0(该行没有被活动的事务锁住,这是可能要进行deferred block cleanout等工做),就把该标志位修改成事务在该块得到的itl的序号,这样当前事务就得到了对记录的锁定,而后就能够修改行数据了,这也就是oracle行锁实现的原理。

相关文章
相关标签/搜索