模拟insert,update和delete造成阻塞的示例

来源:互联网 发布:linux修复系统 编辑:程序博客网 时间:2024/05/16 14:59
会话1SID
BYS@dg2>select distinct sid from v$mystat;

       SID
----------
        17

会话2SID
BYS@dg2>select distinct sid from v$mystat;

       SID
----------
        49


insert造成阻塞的示例
在会话1向表T插入一条数据值1,因为插入数据所在字段有主键约束。
此时会话1不提交或回滚插入操作时,在会话2进行同样的向表T插入一条数据值1时被发生阻塞,语句无法执行。
此时再打开一个会话,可以从v$lock视图中查询出有锁的表及所在会话ID。

会话1:
BYS@dg2>create table t(x number primary key);---新建表,设置主键

Table created.
BYS@dg2>insert into t values(1);    --插入数据不提交

1 row created.
BYS@dg2>
会话2:此时执行插入相同数值时被阻塞----hang住。
BYS@dg2>insert into t values(1);
如果会话1提交,阻塞中止,此时会话2语句执行并报错,提示违反了主键的一致性约束
BYS@dg2>insert into t values(1);
insert into t values(1)
*
ERROR at line 1:
ORA-00001: unique constraint (BYS.SYS_C0011300) violated

会话3:
SID:会话id号
TYPE:锁的类型
ID1:会话操作对象的id号
ID2:ID1+ID2 定位回滚段上的一个地址(即修改之前数据镜像地址),由于138和156会话是一样的说明指向的是同一个地址,换句话说操作的是同一行数据
LMODE:锁模式,不同的数字代表不同的锁模式  例如  0 现在没有申请到锁   3  共享锁模式(段级共享锁)   6  排他锁模式   锁的级别越高限制越多
REQUEST:目前会话没有锁,正在申请的锁模式  例如  0 没有正在申请的锁,说明已经有锁了   6  现在正在申请6号锁,目前因为没有才申请
BLOCK:当前正在阻塞几个会话  例如  1  当前正在阻塞一个会话  2  当前正在阻塞两个会话
锁的实质:是维护一个事务完整性的,锁的信息是数据块的一个属性,是物理的,并不是逻辑上属于某个表或者某几行的。
BYS@dg2>select sid,type,id1,id2,lmode,request,block from v$lock where type in('TM','TX');

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        49 TX      65562        824          0          4          0    --插入的修改值相同才被阻塞,锁级别是4
        49 TM      75052          0          3          0          0
        17 TM      75052          0          3          0          0
        49 TX     327706       1041          6          0          0    --49号会话插入第二条记录未被阻塞
        17 TX      65562        824          6          0          1 -----正在阻塞一个会话
BYS@dg2>select sid,event from v$session_wait where sid in (49,17);

       SID EVENT
---------- ----------------------------------------------------------------
        17 SQL*Net message from client
        49 enq: TX - row lock contention
insert时v$lock视图里面多了一个TX锁(就是最后一行)。
insert和update delete操作的不同,后两者都是对同一条记录的修改权争用产生阻塞(这里不涉及修改值的问题),
而insert操作实际上插入了2条不同的记录,由于这2条不同的记录的修改值一样违反了主键约束从而产生阻塞,实际是对修改值的相同产生了阻塞。锁的级别为4,这种锁比update的锁级别要低,锁的级别越低限制越少。
#####################################################
update造成阻塞的示例
会话1:
BYS@dg2>update t set x=2 where x=1;

1 row updated.
BYS@dg2>
会话二:
BYS@dg2>update t set x=3 where x=1;


会话3
BYS@dg2>select sid,type,id1,id2,lmode,request,block from v$lock where type in('TM','TX');

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        49 TX     196624       1041          0          6          0
        49 TM      75052          0          3          0          0
        17 TM      75052          0          3          0          0
        17 TX     196624       1041          6          0          1
BYS@dg2>select sid,event from v$session_wait where sid in (49,17);

       SID EVENT
---------- ----------------------------------------------------------------
        17 SQL*Net message from client
        49 enq: TX - row lock contention
BYS@dg2>col object_name for a20
BYS@dg2>select object_name from dba_objects where object_id=75052;

OBJECT_NAME
--------------------
T
说明 :17会话在T表加了TM TX锁。TM锁模式为3--共享锁 TX锁模式为6--排它锁。
目前TX锁正在阻塞一个会话-49  可以在49的行看到它在请求一个模式为6的锁。
49会话是当前被阻塞的会话,它操作的对象也是T表(从ID1看)。
TM锁模式也为3(共享锁是有几个会话就可以创建几个共享锁,同时存在).
此时它正在申请17会话所持有的模式为6的锁(操作同一行数据)。


delete造成阻塞的示例
会话1:
BYS@dg2>delete from t;  17会话在删除表内记录-只有一条。未提交,加了TM TX锁

1 row deleted.


会话2:
BYS@dg2>delete from t;  此时在49会话也进行删除表内记录,hang住


会话3:
BYS@dg2>select sid,type,id1,id2,lmode,request,block from v$lock where type in('TM','TX');

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        49 TX     262145        912          0          6          0 --被阻塞了正在申请一个模式6的锁
        49 TM      75052          0          3          0          0
        17 TM      75052          0          3          0          0
        17 TX     262145        912          6          0          1    持有模式6锁,阻塞一个会话

BYS@dg2>select sid,event from v$session_wait where sid in (49,17);

       SID EVENT
---------- ----------------------------------------------------------------
        17 SQL*Net message from client
        49 enq: TX - row lock contention
49会话因TX锁争用导致hang,enq=enqueues队列锁

#####################
select...for update 锁阻塞  这是一种对结果集修改的保护机制
场景:一次性修改多条记录的时候会用到这个命令,起到锁定结果集的效果,这也是结果集修改引起的阻塞
会话1:
BYS@dg2>select * from t where x=2 for update;   对查询出的结果集进行独占,此时不允许其他会话进行修改

         X
----------
         2
会话2:
BYS@dg2>select * from t where x=2 for update;

会话3:
BYS@dg2>select sid,type,id1,id2,lmode,request,block from v$lock where type in('TM','TX');

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        49 TX     589852       1023          0          6          0
        49 TM      75052          0          3          0          0
        17 TM      75052          0          3          0          0
        17 TX     589852       1023          6          0          1
17号会话阻塞49号会话。这种方法可以一次锁定多行记录。一个表上只能有一个6号锁。
BYS@dg2>select sid,event from v$session_wait where sid in (49,17);

       SID EVENT
---------- ----------------------------------------------------------------
        17 SQL*Net message from client
        49 enq: TX - row lock contention

原创粉丝点击