模拟insert,update和delete造成阻塞的示例
会话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