`
tux
  • 浏览: 8548 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

[转]推荐:深入研究ITL阻塞与ITL死锁

阅读更多
但是NinGoo 在下面回复说,10g模拟不到这样的情况了,开始我没有太在意,后来再想想,9i这么做的确是不对的,因为还有其它的进程可以释放资源,根本还没有达到死锁的条件。那么,10g就没有itl死锁了吗?也不是的,10g也有,不过是改进了一下,需要把所有的进程阻塞住的时候,才能爆发出死锁。

从死锁的原理上来看,10g是正确的,9i是欠完善的。我们现在完整的分析一下itl等待,以及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       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该表。
分享到:
评论

相关推荐

    BLOG_【故障处理】Oracle_lhr_队列等待之TX - allocate ITL entry案例.pdf

    - **TX (Transaction)**: 表示这是一个与事务相关的等待事件。 - **Allocate ITL Entry**: 表示正在尝试为事务分配一个新的ITL条目。 #### 二、案例中的故障环境介绍 案例中提到的故障环境包括: - **数据库类型**...

    【故障处理】队列等待之TX 等待事件处理.docx

    ### ITL死锁模拟与Merge语句优化 Merge语句在处理关联和非关联查询时可能会导致ITL竞争。优化Merge语句,尤其是避免全表扫描和不必要的临时表操作,可以减少ITL冲突。 总结,解决Oracle数据库中的队列等待问题需要...

    BLOG_Oracle_lhr_Oracle死锁的分类及其模拟.pdf

    2. **ITL (Intent Lock List) 引发的死锁**:ITL是Oracle中用于记录事务在表空间中锁定信息的数据结构。当多个事务并发操作时,由于ITL槽的限制或者ITL等待时间过长,可能导致死锁。 **ITL概念与结构** Intent Lock...

    oracle ITL事务槽

    Oracle ITL(Interested Transaction List)事务槽是数据库管理系统Oracle中用于处理并发事务处理的重要组成部分,主要存在于数据块的内部。ITL的主要职责是记录在数据块中发生的事务,无论是已提交还是未提交的。每...

    ITL-ports:ITL的端口

    在“ITL-ports”这个主题中,我们将深入探讨ITL如何通过端口实现不同设备之间的通信。 在ITL中,端口扮演着关键角色,它们是数据传输的入口和出口。每个端口都有特定的功能,允许设备发送和接收特定类型的信息。...

    Oracle中关于事务槽(ITL)

    Oracle数据库中的事务槽(ITL, Incident Transaction List)是数据块内部管理并发事务的重要机制。在Oracle中,每个数据块可以包含多个事务槽,用于跟踪并发事务对数据块的更改。当事务对数据块进行读写操作时,就会...

    Bug 9865890 ITL WASTING A LOT OF SPACE IN INDEXES

    Bug 9865890 ITL WASTING A LOT OF SPACE IN INDEXES

    ITL9341_51驱动程序

    ITL9341_51驱动程序是一个针对特定单片机型号——ITL9341的编程组件,主要用于与C51编程语言相配合。在嵌入式系统开发中,驱动程序扮演着至关重要的角色,它们是操作系统与硬件设备之间的桥梁,允许软件应用程序控制...

    自动售货机ITL纸币器升级工具NV11新升级1112.rar

    安装ITL EEPROM Downloader 1.0.4软件,安装完成以后查看电脑开始目录看看是否有这个软件,没有的话到安装目录 C:\Program Files (x86)\ITL EEPROM Downloader去打开这个EEPROM Downloader软件2....

    新建文件夹 (3)_matlab_tx-ITL_

    findp_txITL_beta_cell tx-ITL系统仿真通过输入SNR Nc 等数值进行仿真计算

    英国ITL纸币器二次封装库

    二次封装库的使用可以显著提高开发效率,让开发者无需深入了解硬件底层细节,就能高效地构建基于ITL纸币器的应用程序。同时,通过提供一致的API和面向对象的设计,这样的库也能提高代码的可复用性和可扩展性。 总的...

    NIST (ANSI/NIST-ITL 1-2000) 库(适用于 Windows):读取和写入 ANSI/NIST-ITL 1-2000 格式的文件。-matlab开发

    ANSI/NIST-ITL 1-2000 是美国国家信息系统标准定义的指纹、面部、疤痕和纹身 (SMT) 信息交换的数据格式。 NIST 文件的优点是能够在一个文件中包含有关该人的多个图像和其他类型的数据,这简化了参与方之间的生物...

    Oracle中关于事务槽(ITL).ppt

    主要针对oracle事务槽讲解。一本很经典的电子书。分享给大家

    springboot-postgres-kafka:kafka ITL Hadoop

    让我们深入探讨这些技术以及它们之间的相互作用。 首先,Spring Boot是Java开发框架的一个扩展,旨在简化创建独立的、生产级的基于Spring的应用程序。它内置了默认配置,减少了繁杂的XML配置,并提供了一个快速开发...

    信息安全测试评估技术指南NIST SP 800-115

    信息安全测试评估技术指南NIST SP 800-115是一份由美国国家标准与技术研究院(National Institute of Standards and Technology, NIST)发布的文档,旨在提供信息安全测试和评估的指南。这份文档是2008年9月发布的,...

    理解ORACLE数据库锁机制高效维护医院信息系统运行.pdf

    二是通过数据库的死锁检测机制自动解除死锁;三是优化SQL语句,减少不必要的锁定,例如使用更精确的锁定范围或避免长时间持有锁。 为了降低锁的产生,可以采取以下策略: 1. 使用读一致性视图:通过设置事务的读...

    【转】Oracle数据块深入分析总结

    Oracle 数据块深入分析总结 Oracle 数据块是 Oracle 数据库中最基本的存储单元,每个数据块都包含了数据、索引、事务控制信息等内容。在本文中,我们将对 Oracle 数据块的内部结构进行深入分析,并且使用 dump 和 ...

    itl-ae, 信息理论学习自动编码器.zip

    itl-ae, 信息理论学习自动编码器 使用活页夹在线测试这里代码。国际交易日志信息理论自动编码器,Eder,Matthew Emigh,C 。 IJCNN 2016 ( 接受)安装安装Anaconda环境( 推荐推荐) 。在该环境中,更新 Theano: c

    IT系列红外测温仪说明书.docx

    该系列包括四种型号:ITL-500、IT-5、IT-6和IT-8,每款产品都有其特定的温度测量范围和特性。 ITL-500适用于低温环境,测量范围为0到1200°C,适用于辐射率接近1的常规材料,如塑料、化工和电机热安装等行业。IT-5...

Global site tag (gtag.js) - Google Analytics