Oracle lock之分析

Oracle 锁
Oracle的锁是针对多个会话进行作用的,没有并发就没有锁。
锁的实质:是维护一个事务完整性的,锁的信息是数据块的一个属性,是物理的,并不是逻辑上属于某个表或者某几行的。


Oracle锁的分类

Enqueues --队列类型的锁,通常和业务相关
Latches --系统资源方面的锁,比如内存结构,sql解析。


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

--INSERT 阻塞
CREATE TABLE T (ID INT PRIMARY KEY,NAME VARCHAR2(10)); 


ADMIN@ORCL> INSERT INTO T VALUES(1,'ANKER'); 

1 ROW CREATED. 

--另外一个会话被阻塞
ADMIN@ORCL> INSERT INTO T VALUES(1,'YANGEOO'); 


--从结果可以看出,会话197在请求持有模式为4的TX锁,而被会话9所阻塞
字段解释:
SID:会话id号
TYPE:锁的类型 TM表锁,发生在DML操作时,目的是保证操作能够正常进行,并且阻止其他人对表DDL操作。TX锁 事务锁(行锁)对于被修改的数据,阻止其他会话进行修改。
ID1:会话操作对象的id号
ID2:ID1+ID2 定位回滚段上的一个地址(即修改之前数据镜像地址),若TX锁的ID1+ID2相同,意味着操作的是同一行数据
LMODE:锁模式,不同的数字代表不同的锁模式  例如  0 现在没有申请到锁 3 共享锁模式(段级共享锁) 6 排他锁模式   锁的级别越高限制越多
REQUEST:目前会话没有锁,正在申请的锁模式
BLOCK:当前是否在阻塞会话  例如  1 当前正在阻塞一个会话



admin@ORCL> SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, BLOCK
  2    FROM V$LOCK
  3   WHERE TYPE IN ('TM', 'TX')
  4   ORDER BY SID, TYPE; 

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
         9 TM      15130          0          3          0          0
         9 TX     327692        295          6          0          1
       197 TM      15130          0          3          0          0
       197 TX     327692        295          0          4          0
       197 TX     196629        297          6          0          0
       
--UPDATE 阻塞 

admin@ORCL> update t set NAME = 'ANKER1' where id = 1; 

1 row updated. 

admin@ORCL> update t set name='ANKER2' where id =1; 

--结果可以看出会话197在请求模式为6的TX锁,而此锁已被会话9占用,引起阻塞
admin@ORCL> SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, BLOCK
  2    FROM V$LOCK
  3   WHERE TYPE IN ('TM', 'TX')
  4   ORDER BY SID, TYPE; 

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
         9 TM      15130          0          3          0          0
         9 TX     196610        298          6          0          1
       197 TM      15130          0          3          0          0
       197 TX     196610        298          0          6          0 

--DELETE 阻塞 

admin@ORCL> delete t where ID = 1; 

1 row deleted. 

admin@ORCL> delete t where ID = 1; 

--查看结果,会话197在请求模式6的TX锁,而被会话9阻塞
admin@ORCL> SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, BLOCK
  2    FROM V$LOCK
  3   WHERE TYPE IN ('TM', 'TX')
  4   ORDER BY SID, TYPE; 

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
         9 TM      15130          0          3          0          0
         9 TX     393237        296          6          0          1
       197 TM      15130          0          3          0          0
       197 TX     393237        296          0          6          0
 

 --当出现锁等待时,锁等待对应的事件,
 enq = enqueque
从以下event中也可以看出会话197产生了行锁竞争的事件,也意味着197会话在等待其他会话释放tx锁。

admin@ORCL> SELECT SID,EVENT FROM V$SESSION_WAIT WHERE WAIT_CLASS <> 'Idle'
  2  ;

       SID EVENT
---------- ----------------------------------------------------------------
       197 enq: TX - row lock contention




--2.模拟RI锁定导致阻塞的场景
--经过测试,在主表上insert时,会在从表上加一个3模式的TM锁,而update与delete均不在从表上加锁。
以下测试是对从表操作,导致主表阻塞。
当修改从表时,针对主表update 主键或者delete操作时,均会阻塞住。这是因为在主表修改或删除记录时,它需要查看从表中有没有
对应的值。
创建索引后,就没有这个问题。

admin@ORCL> CREATE TABLE P(ID INT PRIMARY KEY,NAME VARCHAR2(10));
admin@ORCL> CREATE TABLE C (ID REFERENCES P (ID),NAME VARCHAR2(10));
admin@ORCL> insert into p values(1,'A');
admin@ORCL> insert into p values(2,'B');
admin@ORCL> insert into p values(3,'C');

--130会话
admin@ORCL> update c set name = 'E' where id = 1;

1 row updated.

admin@ORCL> SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, BLOCK
  2    FROM V$LOCK
  3   WHERE TYPE IN ('TM', 'TX')
  4   ORDER BY SID, TYPE;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
       130 TM      15515          0          3          0          0
       130 TX     393238        421          6          0          0

--10会话被阻塞
admin@ORCL> delete p where id = 4;

--查看 v$lock,p在进行删除操作时,会在15515表上添加一个4级别的TM锁,导致阻塞。
admin@ORCL> SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, BLOCK
  2    FROM V$LOCK
  3   WHERE TYPE IN ('TM', 'TX')
  4   ORDER BY SID, TYPE;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        10 TM      15513          0          3          0          0
        10 TM      15515          0          0          4          0
       130 TM      15515          0          3          0          1
       130 TX     393238        421          6          0          0

--锁模式与相互的排斥

模式	锁定的SQL				排斥的模式	允许的DML
2	lock table in row share mode		6		select,insert,update,delete,for update
3	lock table in row exclusive mode	4,5,6		select,insert,update,delete,for update
4	lock table in share mode		3,5,6		select
5	lock table in share row exclusive mode	3,4,5,6		select
6	lock table t in exclusive mode		2,3,4,5,6	select

Oracle TM锁的类型
模式2
Row Share(RS)又叫(SS) 
行级共享锁,是限制最少的TM锁,可以提供最高程度的并发性。其他会话可以对锁定的表进行任何类型的DML操作,还可以与其他会话锁并存
Lock table t in row share mode;

 
模式3
Row Exclusive Table Lock(RX)又叫(SX)
行级排他锁,通常已经有事务在修改行或者select…for update 修改结果集。允许其他事务对锁定的表进行select  insert  update  delete 或 lock table 
同时锁定一张表

模式4
Share Table Lock(S)
共享锁,其他事务可以查询锁定的表但不能修改,只允许当前事务修改,但可以多个事务持有它
 
模式5
Share Row Exclusive Table Lock(SRX)又叫SSX
共享行级排他锁,同一时间只允许一个事务持有和修改锁定的表,其他事务可以查询但不能修改
 
模式6
Exclusive Table Lock (X)
排他锁,是限制最高的TM锁,禁止其他事务执行任何类型的DML语句或者锁表
一个表一般只能有一个6号锁

 
--查看当前是否有堵塞
SELECT WAIT_S.SID              AS WAIT_SESSION,
       WAIT_SQL.SQL_TEXT       AS WAIT_SQL,
       WAIT_S.BLOCKING_SESSION AS LOCK_SESSION,
       OBJS.OBJECT_NAME        AS LOCK_OBJECTS,
       OBJS.OBJECT_TYPE        AS LOCK_OBJ_TYPE
  FROM V$SESSION WAIT_S
INNER JOIN V$SQL WAIT_SQL
    ON WAIT_S.SQL_ID = WAIT_SQL.SQL_ID
INNER JOIN V$LOCKED_OBJECT LOCK_OBJ
    ON LOCK_OBJ.SESSION_ID = WAIT_S.BLOCKING_SESSION
INNER JOIN DBA_OBJECTS OBJS
    ON OBJS.OBJECT_ID = LOCK_OBJ.OBJECT_ID
WHERE WAIT_S.LOCKWAIT IS NOT NULL;

--查询哪些session 锁定了哪些object
SELECT S.SID,B.OWNER, B.OBJECT_NAME, S.USERNAME, S.MACHINE, S.TERMINAL, S.PROGRAM
  FROM V$LOCKED_OBJECT L, DBA_OBJECTS B, V$SESSION S
WHERE L.OBJECT_ID = B.OBJECT_ID
   AND L.SESSION_ID = S.SID

猜你喜欢

转载自yangeoo.iteye.com/blog/1965316
今日推荐