深入分析mode 2-6 的TM锁相互间的互斥关系
Oracle TM锁的类型
锁模式 |
锁描述 |
含义 |
锁定表的SQL |
0 |
None |
||
1 |
Null |
空,本模式是oracle预留模式 |
|
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 同时锁定一张表 |
Lock table t in row exclusive mode; |
4 |
Share Table Lock(S) |
共享锁,其他事务可以查询锁定的表但不能修改,只允许当前事务修改,但可以多个事务持有它 |
Lock table t in share mode; |
5 |
Share Row Exclusive Table Lock(SRX) 又叫SSX |
共享行级排他锁,同一时间只允许一个事务持有和修改锁定的表,其他事务可以查询但不能修改 |
Lock table t in share row exclusive mode; |
6 |
Exclusive Table Lock (X) |
排他锁,是限制最高的TM锁,禁止其他事务执行任何类型的DML语句或者锁表 一个表一般只能有一个6号锁 |
Lock table t in exclusive mode; |
Oracle锁模式互斥关系图
锁模式 |
锁名称 |
允许级别 |
互斥级别 |
2 |
行级共享锁 |
2 3 4 5 |
6 |
3 |
行级排他锁 |
2 3 |
4 5 6 |
4 |
共享锁 |
2 4 |
3 5 6 |
5 |
共享行级排他锁 |
2 |
3 4 5 6 |
6 |
排他锁 |
2 3 4 5 6 |
实验锁互斥
准备工作
LEO1@LEO1> select distinct sid from v$mystat; LEO1用户的会话id=138
SID
----------------------------
138
LEO2@LEO1> select distinct sid from v$mystat; LEO2用户的会话id=156
SID
----------------------------
156
LEO1@LEO1> create table lock1 (x int primary key); 创建lock1表,设置x列为主键
Table created.
LEO1@LEO1> insert into lock1 values(1); 我们插入1
1 row created.
LEO1@LEO1> commit; 提交
Commit complete.
LEO1@LEO1> select * from lock1; 现在只有一条记录,并且没有锁
X
----------------------------
1
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
no rows selected
行级共享锁 Row Share(RS) 2
LEO1@LEO1> lock table lock1 in row share mode; 把lock1表设置为行级共享锁模式
Table(s) Locked.
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- -------------------- ---------- ---------- ---------- ---------- ---------- --
138 TM 73472 0 2 0 0
模式标识:2
LEO1@LEO1> select object_name from dba_objects where object_id=73472; lock1表对象id为73472
OBJECT_NAME
----------------------------------------------------------------------------------------------------
LOCK1
LEO2@LEO1> insert into leo1.lock1 values(2);
1 row created.
LEO2@LEO1> select * from leo1.lock1;
X
----------
1
2
LEO2@LEO1> delete from leo1.lock1 where x=1;
1 row deleted.
LEO2@LEO1> select * from leo1.lock1;
X
----------
2
LEO2@LEO1> update leo1.lock1 set x=10 where x=2;
1 row updated.
LEO2@LEO1> select * from leo1.lock1;
X
----------
10
LEO2@LEO1> select * from leo1.lock1 for update;
X
----------
10
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- -------------- ---------- ---------- ---------- -----------------
138 TM 73472 0 2 0 0
156 TM 73472 0 3 0 0
156 TX 524321 936 6 0 0
小结:行级共享锁,是限制最少的TM锁,可以提供最高程度的并发性。其他会话可以对锁定的表进行任何类型的DML操作,还可以与其他会话锁并存。
行级排他锁 Row Exclusive Table Lock(RX) 3
LEO1@LEO1> lock table leo1.lock1 in row exclusive mode; 把lock1表设置为行级排他锁
Table(s) Locked.
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- -------------------- ---------- ---------- --------------------
138 TM 73472 0 3 0 0
模式标识:3
3级锁是一个灵活性比较大的锁,insert delete update 都可以产生一个3级锁,也允许其他事务来修改锁定的表
LEO1@LEO1> select * from leo1.lock1;
X
-----------------
10
20
30
40
50
会话27
LEO1@LEO1> update leo1.lock1 set x=100 where x=10;
1 row updated.
LEO1@LEO1> select * from leo1.lock1; 已经被修改了
X
------------------
20
30
40
50
100
会话156
LEO2@LEO1> insert into leo1.lock1 values(60); 也已经插入了,注意没有提交的事务对别人是不可见的
1 row created.
LEO2@LEO1> select * from leo1.lock1;
X
-----------------
10
20
30
40
50
60
会话146
LEO2@LEO1> delete from leo1.lock1 where x=20; 已经删除
1 row deleted.
LEO2@LEO1> select * from leo1.lock1;
X
--------------------
10
30
40
50
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- ---------------- ---------- ---------- ---------------- ----------
27 TM 73472 0 3 0 0
27 TX 327698 1144 6 0 0
138 TM 73472 0 3 0 0
146 TM 73472 0 3 0 0
146 TX 196626 975 6 0 0
156 TM 73472 0 3 0 0
156 TX 262163 782 6 0 0
大家都是共存的,谁也没有阻塞谁,block列全部是0
小结:行级排他锁,通常已经有事务在修改行或者select…for update 修改结果集。允许其他事务对锁定的表进行select insert update delete 或 lock table 同时锁定一张表。
共享锁 Share Table Lock(S) 4
LEO1@LEO1> select * from leo1.lock1; 还是有5条记录
X
-----------------
10
20
30
40
50
LEO1@LEO1> lock table leo1.lock1 in share mode; 把lock1表设置为共享锁
Table(s) Locked.
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- -------------- ---------- ---------- ---------- ---------- -----
138 TM 73472 0 4 0 0
模式标识:4
4级锁禁止其他会话对锁定的表进行DML操作但可以select查询,还允许多个事物一起持有
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- ------------------ ---------- ---------- ------------------ ----
13 TM 73472 0 0 4 0
27 TM 73472 0 0 3 0
138 TM 73472 0 4 0 1
146 TM 73472 0 0 3 0
156 TM 73472 0 0 3 0
27 146 156 会话都已经被阻塞了,有的朋友会问4级锁可以和4级锁共存这里为什么不行呢。呵呵因为有3级锁在捣乱,4级和3级是不能共存的,所以我们把所有的3级锁都释放就可以了,我们来看一下
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- -------------------- ---------- ---------- ---------- ----------
13 TM 73472 0 4 0 0
27 TM 73472 0 2 0 0
138 TM 73472 0 4 0 0
现在4级锁 2级锁都可以同时存在了
小结:共享锁,其他事务可以查询锁定的表但不能修改,只允许当前事务修改,但可以多个事务持有它。
共享行级排他锁 Share Row Exclusive Table Lock(SRX) 5
LEO1@LEO1> lock table leo1.lock1 in share row exclusive mode; 把lock1表设置为共享行级排他锁
Table(s) Locked.
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- ------------ ---------- ---------- ---------- ------------ -----
138 TM 73472 0 5 0 0
模式标识:5
LEO1@LEO1> select object_name from dba_objects where object_id=73472; 现在锁定的表就是lock1
OBJECT_NAME
--------------------------------------------------------------------------------
LOCK1
会话138
LEO1@LEO1> select * from leo1.lock1; 现在表里有5条记录,我们看看其他会话能不能修改表
X
--------------------
10
20
30
40
50
会话156
LEO2@LEO1> insert into leo1.lock1 values(60); hang住了不能够前进说明被阻塞
会话27
LEO1@LEO1> update leo1.lock1 set x=100 where x=10; hang住了不能够前进说明被阻塞
会话146
LEO2@LEO1> delete from leo1.lock1 where x=20; hang住了不能够前进说明被阻塞
那么select… for update 当然也会被阻塞的,我们来看看其他事务能不能查询呢!
会话23
LEO2@LEO1> select * from leo1.lock1;
X
-------------------
10
20
30
40
50
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- ------------------- ---------- ------------------- ---------- -
27 TM 73472 0 0 3 0
138 TM 73472 0 5 0 1
146 TM 73472 0 0 3 0
156 TM 73472 0 0 3 0
会话23没有被阻塞可以正常查询耶,这也验证了我们的观点,读操作不会被任何事务阻塞,也不会加锁,27 146 156 会话3个行级排他锁都在等待着138会话释放锁
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- ----------
13 TM 73472 0 2 0 0
138 TM 73472 0 5 0 0
会话13的2级锁和会话138的5级锁可以共存符合我们的锁互斥关系
小结:共享行级排他锁,同一时间只允许一个事务持有和修改锁定的表,其他事务可以查询但不能修改。
排他锁 Exclusive Table Lock (X) 6
LEO1@LEO1> lock table leo1.lock1 in exclusive mode; 把lock1表设置为排他锁,等级最高的锁
Table(s) Locked.
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- -------------- ---------- ---------- -------------- ----------
138 TM 73472 0 6 0 0
模式标识:6
会话156
LEO2@LEO1> insert into leo1.lock1 values(60);
会话27
LEO1@LEO1> update leo1.lock1 set x=100 where x=10;
会话146
LEO2@LEO1> delete from leo1.lock1 where x=20;
会话13
LEO2@LEO1> lock table leo1.lock1 in row share mode; 测试锁互斥
LEO1@LEO1> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TM','TX') order by 1,2;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---------- ---------- ---------- ---------- ---------- ---------------- ---------- ---------- ---------- ---------- -------
13 TM 73472 0 0 2 0
27 TM 73472 0 0 3 0
138 TM 73472 0 6 0 1
146 TM 73472 0 0 3 0
156 TM 73472 0 0 3 0
6级锁会阻塞除了自己外的所有会话的事务并且排斥其他的所有锁模式连2级锁都不行,是最高限制的TM锁,当然select还是没有问题的。
小结:排他锁,是限制最高的TM锁,禁止其他事务执行任何类型的DML语句或者锁表。一个表一般只能有一个6号锁。
Leonarding
2012.11.28
天津&winter
分享技术~成就梦想
Blog:www.leonarding.com