ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 浅谈DML阻塞(下)

浅谈DML阻塞(下)

原创 Linux操作系统 作者:realkid4 时间:2012-02-11 21:51:08 0 删除 编辑

 

上面我们提到了关于普通DML操作(insert,update和delete)连带的一些blocking情况。本篇中,我们继续介绍两种连带由于DML操作引起的blocking情况。

 

ü        各种约束引起的block锁定

 

上面谈到的主键锁定block,本质上就是一种约束引起的数据库逻辑blocking。按照这个思路,我们可以猜出具有相同属性的唯一索引(Unique Index)也具有DML操作blocking的问题。

 

 

SQL> alter table t drop constraint PK_T;

Table altered

 

--唯一索引创建

SQL> create unique index u_idx_t on t(id);

Index created

 

SQL> select * from t;

        ID NA

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

         1 dfs

         2 df

 

 

两个会话修改数据表的唯一索引列id。

 

--第一会话

SQL> select sid from v$mystat where rownum<2;

       SID

----------

       156

 

SQL> update t set id=3 where id=1;

1 row updated

 

 

第二会话涉及到相关记录。

 

 

SQL> select sid from v$mystat where rownum<2;

       SID

----------

       144

 

SQL> update t set id=1 where id=2;

(数据被blocking

 

 

此时,锁情况如下:

 

 

SQL> select sid,type,id1,id2,lmode,request,block from v$lock where sid=156 or sid=144 order by sid;

 

       SID TYPE        ID1        ID2      LMODE    REQUEST      BLOCK

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

       144 TX        65554       1246          0          4          0

       144 TM        54736          0          3          0          0

       144 TX       327712       1268          6          0          0

       156 TX        65554       1246          6          0          1

156 TM        54736          0          3          0          0

 

 

从锁的情况来看,基本和主键锁定阻塞的情况相似。

 

作为Unique Index,我们需要注意一点不同之处,就是关于空值null。与主键约束不同,唯一索引列的取值中,是允许存在空值的。唯一索引列中,可能存在多个空值的情况。如果我们要将列值修改为null,那么锁定的几率就会小很多。

 

 

--会话一

SQL> update t set id=null where id=1;

1 row updated

 

--会话二

SQL> update t set id=null where id=2;

1 row updated

 

 

在唯一索引中,null是一种特殊值,是允许重复的。

 

ü        ITL事务槽引起的DML操作锁定

 

我们检查数据字典视图,对数据表T存在两个属性。

 

 

SQL> select INI_TRANS,  MAX_TRANS from dba_tables where table_name='T' and wner='SYS';

 

 INI_TRANS  MAX_TRANS

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

1        255

 

 

在数据表完全定义DDL语句中,也存在相应的片段。

 

 

    "NA" VARCHAR2(10)

   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

 

 

这里我们只简单谈一下maxtrans这个古老的参数体系。我们知道,Oracle数据按照逻辑结构是保存在“表、段、分区和数据块”若干层次结构中的。作为最底层结构的数据块,分为block header和data rows部分。其中,block header中包括了关于数据块的空间分配信息以及事务管理信息。其中的事务信息就是ITL(Interested Transaction List),负责记录该数据块正在进行的事务信息。

 

ITL是有大小的限制的,早期Oracle空间管理中,ITL扮演者很重要的角色。定义数据表的时候,指定的initrans就是每个数据块中最初设置的ITL事务个数。当该数据块发生事务的时候,在ITL上会写入该事务的信息,占据一个ITL位置。当该数据块进行的事务超过initrans设置的时候,数据块就会自动进行拓展动作。拓展的最大个数,就是MaxTrans,默认值为255。

 

设想一种场景,如果我们将数据块的maxtrans设置为很小(Oracle 9i中最小为2),那么同时超过2个会话对同一个数据块的行进行DML操作,就会发生ITL争用阻塞现象。第三个事务就会阻塞。

 

在一些早期出版的Oracle著作中,常用该类型block的演示内容(如Tom的几本名著)。但是注意,这个属性随着Oracle 10g的到来已经被废止,不能显示的设置该参数。该参数也失去了设置的机会。

 

通过命令行语句,可以修改maxtrans属性。

 

 

SQL> alter table t maxtrans 1;

Table altered

 

SQL> select INI_TRANS,  MAX_TRANS from dba_tables where table_name='T' and wner='SYS';

 

 INI_TRANS  MAX_TRANS

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

         1        255

 

 

修改语句并没有变化。

 

但是注意,这并不意味着ITL最大事务槽机制的失效。在资料中,我们找到了下面一段内容:

 

 

Oracle Database now automatically allows up to 255 concurrent update transactions for any data block, depending on the available space in the block.

The database ignores MAXTRANS when specified by users only for new objects created when the COMPATIBLE initialization parameter is set to 10.0 or greater.

 

 

Oracle自动会将255作为事务的最大个数上限,而不是用户的设置。

 

笔者由于只有Oracle 10g以上版本数据库,9i的设置实验无法进行,表示遗憾。

 

3、结论

 

Oracle是一个支持高并发的数据库DBMS系统。借助行锁机制,Oracle向应用提供了较大限度的并发可能性。但是,这种并发并不是绝对的,很多场景都会让多行之间的DML操作相互影响。

 

本文我们讨论了该种机制,以及原因。此外,如外键列需要加索引等等问题,在笔者之前的文章中,已经加以探讨过了。

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-716076/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7566131