1、oracle的锁
锁的作用:保护数据,解决并发问题,后台及大量的前台进程同时访问SGA,需要保持数据的一致性,因为有锁
才有并发,因为锁限制了并发。
应用级锁:对表等资源进行锁定,保证业务逻辑正确性;
数据字典锁:oracle内核程序用于保证数据字典逻辑正确性;
内存控制锁:保护oracle内部数据结构的锁(latch,mutex);
latch锁:chain,链,多个sp对链进行访问导致latch争用,通过简单的底层技术实现,不使用队列机制,十分高效
一个latch可以保护多个内存区域,但一个内存区域只能有一个latch
mutex:比latch开销更小,效率高,
2、LOCK锁:保护数据块,数据行
排他锁(X):A访问后加锁,B不可以访问不能对它读取和修改
通过lock table in exclusive mode命令添加X锁
共享锁(S):A访问后加锁,B也可以读取,但不能修改
通过lock table in share mode命令添加该S锁
DML锁(data locks,数据锁),用于保护数据的完整性;
DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;
内部锁和闩(internal locks and latches),保护 数据库的内部结构。
3、行级锁:DML语句,数据行上加锁标记,锁的粒度越小,并发性越好,sqlserver的锁粒度是数据块
oracle并发性好的原因:对数据行的修改,不影响该数据行所在的块,及另外事务对该行数据的访问(构造CR块),
事务锁TX:因为行级锁产生,一个事务一个事务锁,加在行上
锁的结构
事务锁的加锁和解锁过程:commit,rollback解锁,DML加锁
只有排他锁:不影响读(CR块)
Latch与lock的异同
闩锁(Latch)是一个低级别、轻量级的锁,获得和释放的速度很快。可以简单地理解为闩锁是微观领域的,而lock
则是宏观领域的。latch是用于保护SGA区中共享数据结构的一种串行化锁定机制。它不仅仅用于buffer cache, 还用于
shared pool以及log buffer等。Latch 不会造成阻塞,只会导致等待。Latch是对内存数据结构提供互斥访问的一种机
制,而Lock是以不同的模式来套取共享资源对象,各个模式间存在着兼容或排斥,从这点看出,Latch的访问,包括查询
也是互斥的,任何时候,只能有一个进程能pin住内存的某一块。
Latch只作用于内存中,他只能被当前实例访问,而Lock作用于数据库对象,在RAC体系中实例间允许Lock检测与访问
Latch是瞬间的占用,释放,Lock的释放需要等到事务正确的结束,他占用的时间长短由事务大小决定
Latch是非入队的,而Lock是入队的
Latch不存在死锁,而Lock中存在。
4、表级锁:TM,为了标注事务对表的操作
行级排他锁(Row exclusive)RX锁:因对表修改产生的,可加多个RX锁
锁的兼容性:锁怎么产生,最小限度的减小锁的粒度,目的最大限度的减少锁的影响
A修改一行数据:会在行上加行级X锁,事务加TX锁,表上加TM锁RX
B删除A修改的数据表:需要在表上加X锁,先看是否有RX,X锁与RX互斥
当我们进行DML时,会自动在被更新的表上添加RX锁
允许其他事务通过DML语句修改相同表里的其他数据行
允许使用lock命令对表添加RX锁定
不允许其他事务对表添加X锁
行级共享锁(Row Shared,简称RS锁)
select … from for update --悲观锁
与DML一样,以DML方式读取,加RS锁与RS锁加再同一行数据时互斥
5、锁的兼容性
6、加锁语句以及锁的释放
lock table table_name in [row share][row exclusive][share][share row exclusive][exclusive] mode;
7、锁相关视图
查询会话已获得的锁和正在请求的锁 v$lock
select * from v$lock t;
记录了session已经获得的锁定以及正在请求的锁定的信息
SID:说明session的ID号
TYPE:说明锁定锁定级别,主要关注TX和TM
LMODE:说明已经获得的锁定的模式,以数字编码表示
REQUEST:说明正在请求的锁定的模式,以数字编码表示
BLOCK:说明是否阻止了其他用户获得锁定,大于0说明是,等于0说明否
对于TM锁来说,ID1表示被锁定的对象的对象ID,ID2始终为0s
对于TX锁来说,ID1表示事务使用的回滚段编号以及事务表中对应的记录编号,ID2表示该记录编号被重用的次数(wrap)
锁定模式 锁定简称 编码数值
Row Exclusive RX 3
Row Shared RS 2
Share S 4
Exclusive X 6
Share Row Exclusive SRX 5
NULL N/A 0或者1
select sid,type,id1,id2,decode(lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,
'Share Row Exclusive',6,'Exclusive') lock_mode,decode(request,0,'None',1,'Null',2,'Row share',3,
'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode,block
from v$lock where sid=138;
查询申请锁定被阻塞的session相关信息 v$enqueue_lock
select addr,kaddr,sid,lmode,request,ctime,block from v$enqueue_lock --ctime比阻塞时间
查询被锁定对象及用户信息 v$locked_object,关联dba_objects 查询具体锁定的对象
select XIDUSN,XIDSLOT,XIDSQN,OBJECT_ID,LOCKED_MODE,process,oracle_username from v$locked_object;
select * from dba_objects where object_id = 51151;
oracle中杀掉一个会话
alter system kill session '77,22198'; --sid,||serial#
查询v$enqueue_lock来获得锁定队列中的session信息
select sid,type, decode(request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,
'Share Row Exclusive',6,'Exclusive') request_mode from v$enqueue_lock where sid in(131,153);
查询阻塞和被阻塞信息
select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,decode(b.lmode,0,'None',1,
'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_mode,
b.ctime as time_held,c.sid as waiter_sid,decode(c.request,0,'None',1,'Null',2,'Row share',3,
'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode, c.ctime time_waited
from v$lock b, v$enqueue_lock c, v$session a where a.sid = b.sid and b.id1= c.id1(+) and
b.id2 = c.id2(+) and c.type(+) = 'TX' and b.type = 'TX' and b.block = 1 order by time_held, time_waited;
一个事务修改多行,产生一个TX锁,多个TM(一条语句一个TM)锁
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'a' where department_id=60;
update departments set department_name='unknow' where department_id=10;
update locations set city='unknown' where location_id=1100;
select sid,type,id1,id2, decode(lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,
'Share Row Exclusive',6,'Exclusive') lock_mode, decode(request,0,'None',1,'Null',2,'Row share',3,
'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive')request_mode,block
from v$lock where sid=153;
可以获得的TX锁定的总个数由初始化参数transactions决定,而可以获得的TM锁定的个数则由初始化参数dml_locks决定
select name,value from v$parameter where name in('transactions','dml_locks');
查询当前值,曾经达到的最大值,设置的最大值
select resource_name as "R_N",current_utilization as "C_U",max_utilization as
"M_U",initial_allocation as "I_U" from v$resource_limit
where resource_name in('transactions','dml_locks');
8、死锁
两个session(以A和C来表示),如果A持有C正在申请的锁定,同时C也持有A正在申请的锁定时,这时发生死锁现象。
死锁是典型的“双输”情况,如果任其发展,则会出现A和C这两个session正在执行的事务都无法结束的现象。因此,在
Oracle数据库中,造成死锁的那个DML语句会被撤销。死锁总是由于应用程序设计不合理引起的。当某个session的事务引
起了死锁时,Oracle会自动二次将阻塞该事务的事务撤销,被阻塞事务继续等待。
session 1
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'a' where employee_id between 101 and 105;
session 2
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'b' where employee_id between 106 and 120;
session 1
update employees set last_name=last_name||'c' where employee_id between 106 and 125;
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
session 2
update employees set last_name=last_name||'d' where employee_id between 95 and 104;
死锁发放生后会生成
cd /u01/app/oracle/admin/ipemsdb/bdump/alert_ipemsdb.log --总日志里有死锁信息
ORA-00060: Deadlock detected. More info in file /u01/app/oracle/admin/ipemsdb/udump/ipemsdb_ora_20431.trc.
参考资料:
http://www.poluoluo.com/jzxy/201010/95955.html
http://www.cnblogs.com/sopost/archive/2011/11/17/2253352.html