[转帖]DML操作引起的blocking(二)_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3962 | 回复: 0   主题: [转帖]DML操作引起的blocking(二)        下一篇 
kim
注册用户
等级:中校
经验:1729
发帖:222
精华:0
注册:2011-7-21
状态:离线
发送短消息息给kim 加好友    发送短消息息给kim 发消息
发表于: IP:您无权察看 2011-9-15 10:54:07 | [全部帖] [楼主帖] 楼主

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 515n1g3av68fcVALID                         183enq: 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在锁机制上,已经做到了相当小的范围。




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论