首先说明这篇文章是转载的,原文地址:http://blog.sina.com.cn/s/blog_616b428f0100lwvq.html

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       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=1;
1 row updated.
会话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
Piner@10gR2>update test set a=a
   2     where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
   3       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=1;
1 row updated.
会话4
Piner@10gR2>update test set a=a
   2     where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
   3       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=2;
1 row updated.
以上4个进程把2个不同块的4个itl槽位给消耗光了,现在的情况,就是让他们互相锁住,达成死锁条件,回到会话1,更新块2,注意,以上4个操作,包括以下的操作,更新的根本不是同一行数据,主要是为了防止出现的是TX等待。
Piner@10gR2>update test set a=a
   2     where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
   3       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;
发现被阻塞
那我们在会话3,更新块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)=3;
被阻塞
注意,如果是9i,在这里就报死锁了,在进程1,我们可以看到
Piner@9iR2>update test set a=a
   2     where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
   3       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;
update test set a=a
   where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691 
     and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3
       *
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
但是,在10g里面,这个时候,死锁是不会发生的,因为这里的进程1还可以等待进程4释放资源,进程3还可以等待进程2释放资源,只要进程2与进程4释放了资源,整个环境又活了,那么我们需要把这两个进程也塞住。
会话2,注意,我们也不是更新的同一行数据
Piner@10gR2>update test set a=a
   2     where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
   3       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=4;
被阻塞
还有最后一个进程,进程4,我们也不更新同一行数据
Piner@10gR2>update test set a=a
   2     where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29690
   3       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=4;
虽然,以上的每个更新语句,更新的都不是同一个数据行,但是,的确,所有的进程都被阻塞住了,那么,死锁的条件也达到了,马上,我们可以看到,进程1出现提示,死锁:
Piner@10gR2>update test set a=a
   2     where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
   3       and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;
update test set a=a
   where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=29691
     and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3
       *
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
4、ITL等待与死锁的避免
为了避免以上的情况发生,我们一定要注意在高并发环境下的表中,正确的设置itl个数,如4个,8个等等,保证该块有足够的itl槽位,保证事务能顺利的进行,而没有itl的等待。关于itl的等待,在statspack的段报告中,也能很明显的看到:
  Top 5 ITL Waits per Segment for DB: TEST  Instance: test  Snaps: 13013 -13014
    -> End Segment ITL Waits Threshold:       100
                                              Subobject  Obj.           ITL
    Owner      Tablespace Object Name          Name       Type         Waits  %Total
    ---------- ---------- -------------------- ---------- ----- ------------ -------
    TEST       TBS_EL_IND IDX_LLORDER_ORDERID             INDEX            3   75.00
    TEST       TBS_INDEX2 IDX_AUC_FEED_FDATE              INDEX            1   25.00
如果出现的频率很小,象上面的情况,一般可以不用干预,但是,如果waits很多,则表示这个对象有很严重的itl争用情况,需要增加itl个数。
另外注意的是,有itl等待,并不意味会发生itl死锁,从上面的例子可以看到,发生itl死锁的条件还是瞒苛刻的,如果发生了itl死锁,只能证明,你的系统中,itl等待已经非常严重了。
如果想增加initrans个数,参数可以动态修改,但是,只是针对以后的新块起效,以前的块如果想生效,需要在新参数下,重整表数据,如重建该表,或者move该表。

其它可参考http://wenku.baidu.com/view/36ebeb5177232f60ddcca187.html

文章知识点与官方知识档案匹配,可进一步学习相关知识

[转帖]Oracle数据库中ITL详解的更多相关文章

  1. ASP.NET连接Oracle数据库的步骤详解(转)

    ASP.NET连接Oracle数据库的步骤详解   本文我们主要介绍了ASP.NET连接Oracle数据库的步骤及每个步骤需要进行的设置,希望能够对您有所帮助.   在用ASP.NET开发应用程序时, ...

  2. Oracle数据库的安装详解

    1.写在安装前的话 可能有很多的菜鸟十分害怕大型软件的安装,因为安装过程中的一些错误很让他们头疼.下面我就写一个教程,希望能对大家有帮助,在安装ORACLE之前给大家一点点的意见: (1)尽量要安装L ...

  3. PLSQL连接Oracle数据库问题及详解

    一.Oracle数据库安装步骤参考:https://jingyan.baidu.com/article/363872eccfb9266e4aa16f5d.html 二.Oracle客户端安装:http ...

  4. Oracle数据库中序列(SEQUENCE)的用法详解

    Oracle数据库中序列(SEQUENCE)的用法详解   在Oracle数据库中,序列的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一个值.本文我们主要介绍了 ...

  5. 详解大数据采集引擎之Sqoop&采集oracle数据库中的数据

    一.Sqoop的简介: Sqoop是一个数据采集引擎/数据交换引擎,采集关系型数据库(RDBMS)中的数据,主要用于在RDBMS与HDFS/Hive/HBase之间进行数据传递,可以通过sqoop i ...

  6. Net Core中数据库事务隔离详解——以Dapper和Mysql为例

    Net Core中数据库事务隔离详解--以Dapper和Mysql为例 事务隔离级别 准备工作 Read uncommitted 读未提交 Read committed 读取提交内容 Repeatab ...

  7. 数据库 Oracle监听实例详解

    Oracle实例别名 IMCDB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = )) (CONNECT_D ...

  8. Oracle中ROWID详解

    oracle数据库的表中的每一行数据都有一个唯一的标识符,或者称为rowid,在oracle内部通常就是使用它来访问数据的.rowid需要 10个字节的存储空间,并用18个字符来显示.该值表明了该行在 ...

  9. ORACLE PL/SQL编程详解(转)

    原帖地址:http://blog.csdn.net/chenjinping123/article/details/8737604 ORACLE PL/SQL编程详解 SQL语言只是访问.操作数据库的语 ...

  10. Oracle的exp/imp详解

    原文地址:Oracle的exp/imp详解 作者:jxlazzw 备份概述 逻辑备份:备份可分为两类 ,物理备份和逻辑备份 物理备份:该方法实现数据库的完整恢复,但需要极大的外部存储设备,例如磁带库, ...

随机推荐

  1. Oracle数据库运维场景下,智能运维如何落地生根?

    简介: 「智能运维大数据平台」是一款开箱即用的运维监控平台,通过特有的平台功能可以将企业的基础架构.应用程序.日志管理结合在一起,提供统一采集.统一存储.关联分析.统一监控企业业务保障能力,保障企业业 ...

  2. DVWA Insecure CAPTCHA(不安全的验证码)全等级

    Insecure CAPTCHA(不安全的验证码) 目录: Insecure CAPTCHA(不安全的验证码) 1. Low 2.Medium 3. High 4.Impossible 加载验证码需要 ...

  3. 案例分享-Exception.getMessage突然为null

    背景 之前做的小工具一个jsqlparse+git做的小工具帮我节省时间摸鱼昨天突然停止工作,看了下jvm并没有退出,但是看日志确实有不少Error输出,虽说是一个普通的NPE,但是分析了一下却疑点重 ...

  4. 使用WPF开发自定义用户控件,以及实现相关自定义事件的处理

    在前面随笔<使用Winform开发自定义用户控件,以及实现相关自定义事件的处理>中介绍了Winform用户自定义控件的处理,对于Winform自定义的用户控件来说,它的呈现方式主要就是基于 ...

  5. 神经网络基础篇:向量化(Vectorization)

    向量化 向量化是非常基础的去除代码中for循环的艺术,在深度学习安全领域.深度学习实践中,会经常发现自己训练大数据集,因为深度学习算法处理大数据集效果很棒,所以的代码运行速度非常重要,否则如果在大数据 ...

  6. 华为云GaussDB以技术创新引领金融行业分布式转型

    摘要:分布式数据库以大集群规模.弹性伸缩等优异特性,满足了银行业务发展的多种需求,也因此成为各大银行关键基础设施技术创新建设的首选. 今天,由北京先进数通与华为联合主办的"银行业数字化转型实 ...

  7. 云数据库 GaussDB(for Influx) 解密第十一期:让智能电网中时序数据处理更高效

    摘要:GaussDB(for Influx)是一款基于计算存储分离架构,完全兼容 InfluxDB 生态的云原生时序数据库. 本文分享自华为云社区<云数据库 GaussDB(for Influx ...

  8. 云小课 | ModelArts Pro 自然语言处理套件:高效构建行业高精度文本处理模型

    摘要:ModelArts Pro提供了自然语言处理套件,为客户提供自然语言处理的自定制工具,旨在帮助客户高效地构建行业领域的高精度文本处理模型,可应用于政府.金融.法律等行业. 本文分享自华为云社区& ...

  9. JVM内存模型,你看这一篇就够了

    摘要:JVM是一种用于计算设备的规范,是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的. 本文分享自华为云社区<[云驻共创]JVM内存模型的探知之旅>,作者:多米 ...

  10. 云小课 | DSC:快速识别敏感数据并脱敏

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要: 华为云数据安全中 ...