SQL> select * from
t1;
ID
SQL> alter table t1 add primary key(id);
表已更改。
SQL> select * from v$lock where type in ('TX','TM');
未选定行
SQL> insert into t1
);
已创建
行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TX
会话二:
);
__
(阻塞)
会话一:
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TX
(此处出现申请号锁, TM
TM
TX
TX
SQL> update t1 set
id ;
已更新 行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TX
;
SID
SQL> select sid,event
,);
SID
EVENT
SQL*Net message from
client
SQL*Net message from
client
会话二:
SQL> select
sid ;
SID
;
__(阻塞)
会话一:
,);
SID
EVENT
enq: TX - row lock
contention(等待事件出现tx锁,原因是行锁争用)
SQL*Net message from
client
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TX
(可以看到会话二在申请号锁,而的TX锁block为,表示阻塞了别的会话)
TM
TM
TX
SQL> delete t1 where
id;
已删除 行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TX
;
SID
SQL> select sid,event
,);
SID
EVENT
SQL*Net message from
client
SQL*Net message from
client
会话二:
SQL> select
sid ;
SID
;
__(阻塞)
会话一:
,);
SID
EVENT
enq: TX - row lock
contention(等待事件出现tx锁,原因是行锁争用)
SQL*Net message from
client
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TX
(可以看到会话二在申请号锁,而的TX锁block为,表示阻塞了别的会话)
TM
TM
TX
KADDR
SID:锁所在的会话id
TYPE:锁的类型,类型有很多种,常用的有TX(事务锁)、TM锁(表级锁)
ID1:TM锁为对象的object_id,TX锁为v$transaction 中 XIDUSN *
^ ,TX锁为v$transaction
中 XIDSQN
LMODE:锁的模式,有~,越大锁的限制越高,
REQUEST:为表示没有申请锁,其他~表示在申请该模式的锁
CTIME:表示锁从出现到现在的时间
BLOCK:为表示阻塞了其他会话申请锁,为表示没有阻塞别人。
会话一:
SQL> lock table t1
in share
mode;
表已锁定。
会话二:
SQL> update t1 set
id ;
__(等待)
直到会话一commit或roll,会话二执行。
锁模式 |
锁描述 |
含义 |
锁定表的SQL |
0 |
None |
||
1 |
Null |
空,本模式是oracle预留模式 |
|
2 |
Row Share(RS) 又叫(SS) |
行级共享锁,是限制最少的TM锁,可以提供最高程度的并发性。其他会话可以对锁定的表进行任何类型的DML操作,还可以与其他会话锁并存 |
Lock table t1 in row share mode; |
3 |
Row Exclusive Table Lock(RX) 又叫(SX) |
行级排他锁,通常已经有事务在修改行或者select…for update 修改结果集。允许其他事务对锁定的表进行select insert update delete |
Lock table t1 in row exclusive mode; |
4 |
Share Table Lock(S) |
共享锁,其他事务可以查询锁定的表但不能修改,只允许当前事务修改,但可以多个事务持有它 |
Lock table t1 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语句或者锁表 一个表一般只能有一个号锁 |
Lock table t1 in exclusive |
锁模式 |
锁名称 |
允许级别 |
互斥级别 |
2 |
行级共享锁 |
2 3 4 5 6 |
|
3 |
行级排他锁 |
2 3 |
4 5 6 |
4 |
共享锁 |
2 4 |
3 5 6 |
5 |
共享行级排他锁 |
3 4 5 6 |
|
6 |
排他锁 |
2 3 4 5 6 |
、、SS,表结构共享锁
、SX,表结构共享锁、S, 表结构共享锁、SRX 表结构共享锁、X 表结构排它锁
SS, 表结构共享个S代表表结构共享,第个代表表里的数据共享.
你可以想象一下,当往子表里增 加纪录时,主表的相关主键是不是得处于共享模式.
SX, 用于DML操作,第个S代表表结构共享,第个代表表里被操作的数据独占.
S,
代表表结构+表里的数据都是处于共享模式.当对表创建索引时,在创建期间,表处于这种模式.
SRX)),
X, 删除表是会用上.
号锁
表已锁定。
> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
和号锁
ID
> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TM
TX
可以看到可以共存,没有互斥
号锁
表已锁定。
> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TM
TX
因为和不能共存,因此升级为号锁
号锁,发生等待
__
> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TM
TX
因为同是号会话,上号TM只需将原有升级,但是已经存在号TM,产生互斥,所以等待
in exclusive
mode;
表已锁定。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
;
已更新 行。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TX
;
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
;
已更新 行。
> select sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
SID
TY ID1 ID2 LMODE REQUEST BLOCK
TM
TM
TX
会话一:
SQL> update t1 set
id ;
已更新
行。
会话二:
;
已更新 行。
会话一:
SQL> update t2 set
id ;
__(等待)
会话二:
SQL> update t1 set
id ;
__(等待)
会话一:
SQL> update t2 set
id ;
行出现错误:
ORA:
等待资源时检测到死锁
在讲到lock的上文中已经提到,这种控制机制需要resource,lock联众数据结构,但是需要内存分配lock数据结构,对于粗粒度(可以理解为文件很大)或者数量有限的资源,使用这种机制还可以接受,因为分配的内存并不多。但是对于表的数据记录,动辄几百G
的表,每个记录如果都分配一个resource 和lock
数据结构对,无论从内存需求还是维护开销上都是一个噩梦。所以,对于数据记录这种细粒度的资源,oracle使用的是行级锁(row level
lock)。记数据块内存储的是一条条的用户记录,用户记录也是按照一定的格式保存的,每条记录可以分成 记录头 和 记录体
两部分。记录头中是描述信息,比如列宽度,和事务有关的是ITL Entry pointer字段。
这种锁保护的资源是回滚段,回滚数据块。因此这个申请也就意味着:用户必须先申请到一个回滚段资源后才能开始一个事务,才能执行语句修改数据。申请到回滚段资源后,用户事务就可以修改数据了。在修改数据表的记录时,需要遵循下面的操作顺序: