ITPub博客

首页 > Linux操作系统 > Linux操作系统 > DML操作引起的blocking(二)

DML操作引起的blocking(二)

原创 Linux操作系统 作者:realkid4 时间:2011-02-20 00:01:49 0 删除 编辑

 

2、并行插入相同主键记录

 

我们尝试构建一个同时插入主键相同的记录,看看Oracle是如何处理这样的情况。这两条数据就是相关数据,因为正常条件下,两条数据是无法并存的。

 

 

//session1(sid=158)中

 

SQL> insert into t values (1,'ddd');

 

已创建 1 行。

 

//session2(sid=141)中

 

SQL> insert into t values (1,'ddddfsf');

session2被阻塞)

 

 

发生了阻塞!session2因为插入了id=1的数据,但是之前已经存在id=1的记录,即使这条记录还没有被commit。

 

//查看现象

SQL> select * from v$locked_object;

 

    XIDUSN    XIDSLOT     XIDSQN  OBJECT_ID SESSION_ID ORACLE_USERNAME                OS_USER_NAME                   PROCESS      LOCKED_MODE

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

         8         19        891      53606        141 SCOTT IBM-VS2A1BHCNS0\ibm  772:3932  3

         6         17        840      53606        158 SCOTT      IBM-VS2A1BHCNS0\ibm 636:1036               3

 

SQL> select * from v$lock where sid in (141,158);

 

ADDR     KADDR           SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME BLOCK

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

6C8344A8 6C8344BC        141 TX       393233        840          0          4         96 0

6BDC4074 6BDC408C        158 TM        53606          0          3          0        129 0

6BDC4138 6BDC4150        141 TM        53606          0          3          0         96 0

6BE185A8 6BE186C4        158 TX       393233        840          6          0        129 1

6BE29A54 6BE29B70        141 TX       524307        891          6          0         96 0

 

 

 

SQL> select sid, serial#, lockwait, sql_id, blocking_session_status,EVENT#, EVENT

  2  from v$session where sid in (141,158);

 

       SID    SERIAL# LOCKWAIT SQL_ID        BLOCKING_SESSION_STATUS     EVENT# EVENT

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

       158         47                        NO HOLDER                      256 SQL*Net message from client

       141        122 6C8344BC 515n1g3av68fc VALID                          183 enq: TX - row lock contention

 

首先,我们分析一下v$locked_object视图。两个会话session分别在undo表空间分配了相应的空间,准备存放undo数据镜像。并且给这两个段加入了共享锁(Lmode=3)。

 

v$lock视图变得略有复杂。首先,我们观察session1(sid=158)的情况。session1的情况和上面没有多少区别。现在数据表T上加一个共享对象锁(TM锁,Lmode=3)。之后,在Undo区(393233/840)上分配空间,保存数据镜像,并且加入了一个排他锁(TX Lmode=6)。当session1(sid=158)完成之后,session2(sid=141)尝试将相同id的数据插入到数据表中。首先,先给对象T加入一个共享锁对象(TM锁,LMODE=3)。之后,session2尝试给已经为session1排他(lmode=6)的undo空间(393233/840),加一个TX锁,类型为lmode=4(共享锁类型),要求共享undo空间(393233/840)。这样,session1和session2在这个undo空间上存在了blocking,因为lmode4和6之间不能并存。于是,session2被blocking。

 

此外,session2为了进行insert操作,还分配了一个新的undo空间(53606          0),实行lmode=3的事务锁。

 

从会话v$session等待情况看,会话2在等待事件“enq: TX - row lock contention”,等待session1释放数据行锁。

 

 

结论:当两个会话在同时新增加一个记录的时候,如果输入的主键相同,一个会话会发生blocking。此时,Oracle是难以做决定,前一个会话如果被rollback,第二个事务不存在问题。如果前一个会话提交,第二个事务对应数据行就是非法的数据。在这种情况下,Oracle只能是blocking一个会话了。

 

 

 

3、同时修改相同一条记录

 

当我们尝试修改一条相同的记录时,会发生什么呢?

 

 

//session1(sid=158)

 

SQL> update t set name='dfs' where id=1;

 

已更新 1 行。

 

SQL>

 

//session2(sid=141)

 

SQL> update t set name='fs' where id=1;

(阻塞)

 

 

出现了阻塞blocking。我们观察一下锁的情况。

 

 

SQL> select * from v$locked_object;

 

    XIDUSN    XIDSLOT     XIDSQN  OBJECT_ID SESSION_ID PROCESS      LOCKED_MODE

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

         0          0          0      53606        141 772:3932               3

         6         16        840      53606        158 636:1036               3

 

SQL> select * from v$lock where sid in (141,158);

 

ADDR     KADDR           SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME  BLOCK

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

6C8344A8 6C8344BC        141 TX       393232        840          0          6         42 0

6BDC4074 6BDC408C        158 TM        53606          0          3          0         87 0

6BDC4138 6BDC4150        141 TM        53606          0          3          0         42 0

6BE185A8 6BE186C4        158 TX       393232        840          6          0         87 1

 

 

SQL> select sid, serial#, lockwait, sql_id, blocking_session_status,EVENT#, EVENT

  2  from v$session where sid in (141,158);

 

       SID    SERIAL# LOCKWAIT SQL_ID        BLOCKING_SESSION_STATUS     EVENT# EVENT

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

   141         47 6C8344BC fgjfccu4as8xv VALID       83 enq: TX - row lock contention

158        122                      NO HOLDER  256 SQL*Net message from client

 

 

从视图情况下,虽然在修改相同数据行的时候,都是后一个session2被阻塞住。但是,在加锁方式上存在一些差异。这点从v$lock视图上可以分析出。

 

先看v$locked_object,session2(sid=141)的undo空间锁是没有建立的,前三个数据列为0。

 

v$lock视图中,session2发起了两个锁,一个是对数据表的共享锁TM。另一个锁是对session1所开启的undo段进行行排他(Lmode=6)要求。因为其上已经存在session1的排他,两者不能并存。于是,session2被阻塞住。

 

 

结论:当两个会话在同时修改一个数据时。对共享资源的占用就是第一个会话undo段空间对象。后一个session会被blocking。

 

 

4、删除相同的数据

 

最后我们看看删除数据时候的情况。

 

//session1(sid=149)

SQL> conn scott/tiger@orcl;

已连接。

 

SQL> delete t where id=1;

 

已删除 1 行。

 

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

 

       SID

----------

       149

 

//session2(Sid=156)

SQL> conn scott/tiger@orcl

已连接。

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

 

       SID

----------

       156

 

SQL> delete t where id=1;

 

 

删除相同的数据时,被blocking。

 

 

 

SQL> select * from v$locked_object;

 

    XIDUSN    XIDSLOT     XIDSQN  OBJECT_ID SESSION_ID ORACLE_USERNAME  OS_USER_NAME  PROCESS   LOCKED_MODE

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

   8         22        896      53606        149 SCOTT  IBM-VS2A1BHCNS0\ibm   3752:588 3

   0         0         0        53606    156 SCOTT IBM-VS2A1BHCNS0\ibm  1428:3376   3

 

 

SQL> select * from v$lock where sid in (149,156);

 

ADDR     KADDR           SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

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

6C8344A8 6C8344BC        156 TX       524310        896          0          6        130 0

6BDC4074 6BDC408C        149 TM        53606          0          3          0        309 0

6BDC4138 6BDC4150        156 TM        53606          0          3          0        130 0

6BE23C64 6BE23D80        149 TX       524310        896          6          0        309 1

 

 

SQL> select sid, serial#, lockwait, sql_id, blocking_session_status,EVENT#, EVENT

  2  from v$session where sid in (149,156);

 

       SID    SERIAL# LOCKWAIT SQL_ID        BLOCKING_SESSION_STATUS     EVENT# EVENT

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

149        381                        NO HOLDER      256 SQL*Net message from client

156           493 6C8344BC g2pvqwhq0pwjc VALID          183 enq: TX - row lock contention

 

 

删除的特征和修改相同,都是两个会话争用这个数据行对应的锁,之后发生锁互斥现象,引发blocking。

 

 

结论:在删除两条相同数据行的情况下,是可能发生blocking的。

 

 

综合上面的研究,我们可以发现。Oracle采用的多版本一致度和事务行锁机制,最大限度的保证了并行特性发挥。但是,存在并行、存在资源独占使用,就存在锁机制,有锁机制就意味着总会有访问被串行化。但是,不得不承认,Oracle在锁机制上,已经做到了相当小的范围。

 

 

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

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

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7744935