本篇只注重相关原理研究,不涉及诊断案例。
Oracle的锁(lock)机制用于管理对共享资源的并发访问,注意,是“共享资源”而不是“数据库行”。当然Oracle会在行级对表数据锁定,这固然不错,不过Oracle也会在其他多个级别上使用锁,从而对多种不同的资源提供并发访问。例如,执行一个存储过程时,过程本身会以某种模式锁定,以允许其他用户执行这个过程,但是不允许另外的用户以任何方式修改这个过程。数据库中使用锁是为了支持对共享资源进行并发访问,与此同时还能提供数据完整性和一致性。
经常把锁分为3大类:
DML锁(Data Manipulation Locks)-用来保护数据的完整性和一致性。
DDL锁(Data Dictionary Locks-用来保护数据对象的结构,如table,index的定义。
系统级锁(Latch、mutex、library cache pin/lock)- 用来保护数据库内部结构,如sga内存结构。
2.1Oracle锁视图
Oracle中ddl锁和dml锁的视图有:dba_ddl_locks、dba_dml_locks其中dba_ddl_locks的视图定义如下:
create orreplace view dba_ddl_locks as
select ……
from v$session s, x$kglob ob, x$kgllk lk
where lk.kgllkhdl = ob.kglhdadr
and lk.kgllkuse = s.saddr
and ob.kglhdnsp != 0;
而dba_dml_locks的视图定义如下:
create orreplace view dba_dml_locks as
select ……
from (selectl.laddr addr, l.kaddr kaddr, * 1040651:Defn for v$lock */
s.ksusenum sid, r.ksqrsidttype, r.ksqrsid1 id1,
r.ksqrsid2 id2, l.lmodelmode, l.request request,
l.ctime ctime, l.block block
from v$_lock l, x$ksuse s, x$ksqrsr
where l.saddr = s.addr andl.raddr = r.addr and
s.inst_id =USERENV('Instance')) l, obj$ o, user$ u
where l.id1 = o.obj#
and o.owner# = u.user#
and l.type = 'TM';
所以,在Oracle中,DDL锁其实应该是与x$kgllk有关的library cache方面的锁(library cache lock),而DML锁是指enqueue上的TM锁,$ksqrs是指kernel service enqueue resource。而enqueue中的其它类型,既不属于DDL锁与不属于DML锁,我们就称之为系统级enqueue。所以我们讨论DML锁,其实就是讨论TM enqueue。而讨论DDL锁,实际应该是讨论library cache方面的内容。
2.2Enqueue概念
enqueue是共享内存结构,用于串行化访问数据库资源。enqueue又分为用户级enqueue和系统级enqueue。
用户类型的enqueue有:
TM - DML (Table Manipulation)
TX - Transaction Enqueue used to protecttransaction information.
UL - User Lock Enqueue used when anapplication makes use of the DBMS_LOCK package.
系统类型的enqueue有:
BF enqueue
CF Controlfile Enqueue
DX Distributed Transaction Enqueue
FB Block Format Enqueue
HW High Water Enqueue
JS Job Scheduler Enqueue
RO Fast Object Reuse Enqueue
SQ Sequence Cache Enqueue
ST Space Transaction Enqueue
TO Temporary Table Object Enqueue
TT Tablespace Operations Enqueue
US Undo Segment Enqueue
2.3Library Cache概念
Librarycache是Shared pool的一部分,它几乎是Oracle内存结构中最复杂的一部分,主要存放shared curosr(SQL)和PLSQL对象(function,procedure,trigger)的信息,以及这些对象所依赖的table,index,view等对象的信息。
LibraryCache的结构如下所示:

LibraryCache中保存的对象,可以查看v$db_object_cache视图。从v$db_object_cache视图的定义可以看出,在该视图上有librarycache object对象上存在多少个pin和lock,但是具体是哪个会话加了pin或lock,在该视图上没有表现。
SQL> descV$DB_OBJECT_CACHE

2.4锁等级
在enqueue、library cache和latch中都有锁的等级概念,但我们一般只讨论enqueue中的锁等级概念,latch和library cache中锁等级涉及的方面较少。
x$kgllk中锁等级的定义:在kgllkmod和kgllkreq字段上定义了持有和请求x$kgllk资源的锁级别,其中锁级别如下:0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive',这个可以通过dba_ddl_locks视图的定义可以观察到。
而enqueue中的锁等级可以参考:VIEW: "V$LOCK"Reference Note [ID 29787.1]
0 - none
1 - null (NULL)
2 - row-S (SS)
3 - row-X (SX)
4 - share (S)
5 - S/Row-X (SSX)
6 - exclusive (X)
2.5锁冲突
如果会话请求相关锁的锁级别,和其它会话持有该锁的锁级别有冲突,那申请锁的会话会被挂住。总体原则如下:如果申请的锁级别小于持有的锁级别,那申请会话会被挂住等待。
如:某个会话持有4级TM锁(v$lock中LMODE=4),而某个会话想以3级(v$lock中REQUEST=3)来请求TM锁,那请求会话是得不到TM锁的,这就是锁冲突,除非持有4级TM锁的会话释放TM锁。
关于锁冲突的情况,需要关注和研究的一般是enqueue锁,具体可以参考:VIEW: "V$LOCK"Reference Note [ID 29787.1]
而其实Library Cache中也是存在锁冲突,这从v$db_object_cache的定义中可以看出来,只是Library Cache锁的级别较少,只有3级。
selectinst_id,
kglnaown,
......
decode(kglhdlmd,
0, 'NONE',
1, 'NULL',
2, 'SHARED',
3, 'EXCLUSIVE',
'UNKOWN'),
decode(kglhdpmd,
0, 'NONE',
1, 'NULL',
2, 'SHARED',
3, 'EXCLUSIVE',
'UNKOWN'),
decode(kglobsta,
1, 'VALID',
2, 'VALID_AUTH_ERROR',
3, 'VALID_COMPILE_ERROR',
4, 'VALID_UNAUTH',
5, 'INVALID_UNAUTH',
6, 'INVALID',
'UNKOWN'),
......
from x$kglob
where kglnaobj is not null。
enqueue锁冲突的表现为enq类型的等待事件,而实际上锁的详细情况(如持有者,阻塞者或者其它情况)是在v$lock表中。而很多enq类型的等待事件,其中p1、p2、p3列的信息就是v$lock中的id1和id2。当然其它的enq类型的等待事件的p1、p2、p3,其实也是v$lock的id1和id2的反映。
具体检查等待事件p1、p2、p3字段的含义,可以查询v$event_name。而查看v$lock的id1、id2的含义,可以查询v$lock_type。
而在libarary cache上的锁冲突的表现为:library cache %类型、cursor:%类型的等待事件,其中library cache类型的等待事件是library cache lock、library cache pin相关的锁,而cursor:%类型的等待事件对应的是相关的mutex。
中国OCM之家
专注数据 共现梦想
QQ群:554334183






