Library cache lock/pin详解

时间:2022-11-16 05:27:34

Library cache lock/pin

一、概述

---本文是网络资料加metalink 等整理得来
一个实例中的library cache包括了不同类型对象的描述,如:游标,索引,表,视图,过程,等等. 这些对象不能在他们被使用的时候改变,他们在被使用的时候会被一种library locks and pins的机制锁住. 一个会话中,需要使用一个对象,会在该对象上先得到一个library lock(null, shared or exclusive模式的)这是为了,防止其他会话也访问这个对象(例如:重编译一个包或视图的时候,会加上exclusive类型的锁)或更改对象的定义.

总的来说,library cache pin和library cache lock都是用于share pool的并发控制的。pin和lock都可以看作是一种锁。locks/pins会在SQL语句执行期间一直保持,在结束的时候才释放。Lock锁的等级比pin要高。

 

每个想使用或修改已经locked/pin的对象的SQL语句,将会等待事件'library cache pin'或'library cache lock'直到超时.超时,通常发生在5分钟后,然后SQL语句会出现ORA-4021的错误.如果发现死锁,则会出现ORA-4020错误

二、library cache pin和library cache lock成因
lock主要有三种模式: Null,share(2),Exclusive(3).
在读取访问对象时,通常需要获取Null(空)模式以及share(共享)模式的锁定.
在修改对象时,需要获得Exclusive(排他)锁定.

同样pin有三种模式,Null,shared(2)和exclusive(3).
只读模式时获得共享pin,修改模式获得排他pin.

模式为shared(2)的pin会阻塞任何exclusive(3)的pin请求。
模式为shared(3)的pin也会阻塞任何exclusive(2)的pin请求。

不同的操作会对对象请求不同的lock/pin
1、所有的DDL都会对被处理的对象请求排他类型的lock和pin
2、对视图,过程,包的编译都要请求排他的lock和pin

当要对一个过程或者函数进行编译时,需要在library cache中pin该对象。在pin该对象以前,需要获得该对象handle的锁定,如果获取失败,就会产生library cache lock等待。如果成功获取handle的lock,则继续在library cache中pin该对象,如果pin对象失败,则会产生library cache pin等待。

如果是存储过程或者函数,可以这样认为:如果存在librarycache lock等待,则一定存在library cache pin等待;反过来,如果存在library cache pin等待,不一定会存在library cache lock等待;
但如果是表引起的,则一般只有library cache lock等待,则不一定存在library cache pin。

可能发生library cache pin和library cache lock的情况:
1、在存储过程或者函数正在运行时被编译。
2、在存储过程或者函数正在运行时被对它们进行授权、或者移除权限等操作。
3、对某个表执行DDL期间,有另外的会话对该表执行DML或者DDL。
4、PL/SQL对象之间存在复杂的依赖性

每个想使用或修改已经locked/pin的对象的SQL语句,将会等待事件'library cache pin'或'library cache lock'直到超时.
超时,通常发生在5分钟后,然后SQL语句会出现ORA-4021的错误.如果发现死锁,则会出现ORA-4020错误。

例如:
SES1:
执行:exec p_sleep;
假设存储过程p正在运行,且运行时间很长
SES2:
执行:grant execute on p_sleep to system
对p进行编译,如果之前没有其他会话lock存储过程p的handle,则本会话会将获取p的handle锁定;但会话pin p时会失败,此时在SES2上产生library cache pin等待。如果超过5分钟仍然不能完成pinp,则会报错:
ORA-04021: 等待锁定对象 SUK.P_SLEEP 时发生超时。此时,本会话会释放p的handlelock。(也可能是ORA-04020错误)
SES3:
执行:grant execute on p_sleepto system
在这个会话中继续编译p,则该会话在获取p的handle锁定时会失败,在本会话产生librarycache lock等待。如果SES2超时,则本会话会获取p的handlelock,v$session_wait上的等待事件也由librarycache lock变成ibrary cache pin,直到超时。

librarycache pin
查询v$session_wait视图中library cache pin对应的P1、P2、P3
P1 = Handle address
这个就是引起library cache pin等待的对象被pin到library cache中的handle。一般用P1RAW(十六进制)代替p1(十进制)
可以用以下sql查询那个用户下的那个对象正在被请求pin:
SELECT kglnaown "Owner", kglnaobj "Object"
FROM x$kglob
WHERE kglhdadr='&P1RAW'

返回的OBJECT可能是具体的对象,也可能是一段SQL。

P2 =Pin address
自身的pin地址。一般用P2RAW(十六进制)代替P2(十进制)

P3 = Encoded Mode & Namespace

library cache pin和library cache lock(一)我们简单介绍了介绍library cache pin和librarycache lock的成因,下面介绍如何解决library cache pin和library cache lock等待。

三、解决方法

有两种方法可以查询library cache pin的相关信息,推荐使用第二种。

使用这种方法前,有必要先了解以下表或视图:x$kglob、x$kgllk、x$kglpn、DBA_KGLLOCK

1) x$kglob
该基表主要是library cache object的相关信息。
X$KGLOB--[K]ernel [G]eneric [L]ibrary Cache Manager [OB]ject
引用该基表的视图有﹕GV$ACCESS、GV$OBJECT_DEPENDENCY、GV$DB_OBJECT_CACHE、GV$DB_PIPES、DBA_LOCK_INTERNAL﹑DBA_DDL_LOCKS

2) x$kgllk
该基表保存了library cache中对象的锁信息,主要用于解决library cache lock。
其名称含义是:
[K]ernel Layer 
[G]eneric Layer 
[L]ibrary Cache Manager ( defined and mapped from kqlf ) 
Object Locks 
X$KGLLK - Object [L]oc[K]s

引用该基表的视图有﹕
DBA_DDL_LOCKS ﹑DBA_KGLLOCK ﹑GV$ACCESS﹑GV$OPEN_CURSOR

SQL> desc x$kgllk;
名称 类型
---------- -----------
ADDR RAW(4)
INDX NUMBER
INST_ID NUMBER
KGLLKADR RAW(4)
KGLLKUSE RAW(4) ---会话地址(对应v$session的saddr)
KGLLKSES RAW(4) ---owner地址
KGLLKSNM NUMBER ---SID
KGLLKHDL RAW(4) ---句柄
KGLLKPNC RAW(4) ---the address of the call pin
KGLLKPNS RAW(4) ---对应跟踪文件中的session pin值 
KGLLKCNT NUMBER 
KGLLKMOD NUMBER ---持有锁的模式(0为nolock/pin held﹐1为null,2为share﹐3为exclusive) 
KGLLKREQ NUMBER ---请求锁的模式(0为nolock/pin held﹐1为null,2为share﹐3为exclusive) 
KGLLKFLG NUMBER ---cursor的状态﹐8(10g前)或2048(10g)表示这个sql正在运行﹐
KGLLKSPN NUMBER ---对应跟踪文件的savepoint的值
KGLLKHTB RAW(4)
KGLNAHSH NUMBER ---sql的hash值(对应v$session的sql_hash_value)
KGLLKSQLID VARCHAR2(13) ---sql ID,sql标识符
KGLHDPAR RAW(4) ---sql地址(对应v$session的sql_address) 
KGLHDNSP NUMBER
USER_NAME VARCHAR2(30) ---会话的用戶名
KGLNAOBJ VARCHAR2(60) ---对象名称或者已分析并打开cursor的sql的前60个字符

3) x$kglpn
X$KGLPN--[K]ernel [G]eneric [L]ibrary Cache Manager object [P]i[N]s 
它是与x$kgllk相对应的表﹐是关于pin的相关信息。它主要用于解决library cache pin
引用该表的视图有﹕
DBA_KGLLOCK

SQL>desc x$kglpn;
名称 类型
------------ ----------------------------
ADDR RAW(4)
INDX NUMBER
INST_ID NUMBER
KGLPNADR RAW(4)
KGLPNUSE RAW(4) ---会话地址(对应v$session的saddr)
KGLPNSES RAW(4) ---owner地址
KGLPNHDL RAW(4) ---句柄
KGLPNLCK RAW(4)
KGLPNCNT NUMBER
KGLPNMOD NUMBER ---持有pin的模式(0为no lock/pin held﹐1为null,2为share﹐3为exclusive) 
KGLPNREQ NUMBER ---请求pin的模式(0为no lock/pin held﹐1为null,2为share﹐3为exclusive)
KGLPNDMK NUMBER
KGLPNSPN NUMBER ---对应跟踪文件的savepoint的值

4) DBA_KGLLOCK
DBA_KGLLOCK是一个视图,它联合了x$kgllk和x$kglpn的部分信息。 
通过查询,我们可以知道DBA_KGLLOCK视图的构建语句:
SQL> SELECT * FROM DBA_VIEWS WHERE VIEW_NAME='DBA_KGLLOCK';

select kgllkuse, kgllkhdl, kgllkmod, kgllkreq, 'Lock' kgllktype from x$kgllk 
union all 
select kglpnuse, kglpnhdl, kglpnmod, kglpnreq, 'Pin' kgllktype from x$kglpn

了解了用到的几个主要视图或表的结构,我们就可以写出编写查询来查看相关信息:
方法一、只能查询librarycache pin相关信息
SQL> SELECT distinct decode(kglpnreq,0,'holding_session:'||s.sid,'waiting_session: '||s.sid) sid,
2 s.SERIAL#, kglpnmod "Pin Mode", kglpnreq "ReqPin",a.sql_text,kglnaown "Owner", kglnaobj "Object"
3 FROM x$kglpn p, v$session s,v$sqlarea a,v$session_wait sw,x$kglob x
4 WHERE p.kglpnuse=s.saddr
5 AND kglpnhdl=sw.p1raw
6 and kglhdadr=sw.p1raw
7 and event like 'library cache%'
8 and (a.hash_value, a.address) IN (
9 select
10 DECODE (sql_hash_value,
11 0,
12 prev_hash_value,
13 sql_hash_value
14 ),
15 DECODE (sql_hash_value, 0, prev_sql_addr, sql_address)
16 from v$session s2
17 where s2.sid=s.sid
18 )
19 ;

SID SERIAL# Pin Mode Req Pin SQL_TEXT Owner Object
-------------------- ---------- ---------- -------------------------------------------------- ------------ --------------------
blocked_sid: 16 195 0 3 grant execute on p_s SUK P_SLEEP
blocker_sid: 20 15 2 0 begin p_sleep; end; SUK P_SLEEP

得到这个结果后,你可以根据实际情况kill掉阻塞的会话或者被阻塞的会话。

方法二、可以查询library cache pin和library cache lock 的信息

selectDistinct /*+ ordered */ w1.sid waiting_session,
h1.sid holding_session, 
w.kgllktype lock_or_pin, 
od.to_owner object_owner, 
od.to_name object_name, 
oc.Type, 
decode(h.kgllkmod, 0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive', 
'Unknown') mode_held, 
decode(w.kgllkreq, 0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive', 
'Unknown') mode_requested,
xw.KGLNAOBJ wait_sql,xh.KGLNAOBJ hold_sql 
from dba_kgllock w, dba_kgllock h, v$session w1, 
v$session h1,v$object_dependency od,V$DB_OBJECT_CACHE oc,x$kgllk xw,x$kgllk xh
where 
(((h.kgllkmod != 0) and (h.kgllkmod != 1) 
and ((h.kgllkreq = 0) or (h.kgllkreq = 1))) 
and 
(((w.kgllkmod = 0) or (w.kgllkmod= 1)) 
and ((w.kgllkreq != 0) and (w.kgllkreq != 1)))) 
and w.kgllktype = h.kgllktype 
and w.kgllkhdl = h.kgllkhdl 
and w.kgllkuse = w1.saddr 
and h.kgllkuse = h1.saddr 
And od.to_address = w.kgllkhdl 
And od.to_name=oc.Name 
And od.to_owner=oc.owner 
And w1.sid=xw.KGLLKSNM
And h1.sid=xh.KGLLKSNM 
And (w1.SQL_ADDRESS=xw.KGLHDPAR And w1.SQL_HASH_VALUE=xw.KGLNAHSH)
And (h1.SQL_ADDRESS=xh.KGLHDPAR And h1.SQL_HASH_VALUE=xh.KGLNAHSH) 
;

WAITING_SESSION HOLDING_SESSION LOCK_OR_PIN OBJECT_OWNER OBJECT_NAME TYPEMODE_HELD MODE_REQUESTED WAIT_SQL HOLD_SQL
--------------- --------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------- --------------------------------------------------------------------------------------------------------------------------------------
18 19 Lock SUK P_SLEEP PROCEDURE Exclusive Exclusive grant execute on p_sleepto system grant execute on p_sleep to system
19 12 Pin SUK P_SLEEP PROCEDURE Share Exclusive grant execute on p_sleep tosystem begin p_sleep; end;
23 25 Lock SUK P_SLEEP2 PROCEDURE Exclusive Exclusive grant execute on p_sleep2to system grant execute on p_sleep2 to system
25 14 Pin SUK P_SLEEP2 PROCEDURE Share Exclusive grant execute on p_sleep2 tosystem begin p_sleep2; end;

为了避免这种情况,可以在编译过程或函数等对象时,先查看一下是否有会话正在使用该对象,查询语句如下:

SELECT Distinct sid using_sid, 
s.SERIAL#, kglpnmod "Pin Mode", kglpnreq "Req Pin",kglnaown"Owner", kglnaobj "using_Object"
FROM x$kglpn p, v$session s,x$kglob x 
WHERE p.kglpnuse=s.saddr 
AND kglpnhdl=kglhdadr 
And p.KGLPNUSE = s.saddr 
And kglpnreq=0 
And upper(kglnaobj) = upper('&obj');

如果有结果返回,则等待这些对话的操作执行完毕再重新编译,也可以把这些会话kill。

四、其他解决方法
上面主要是用到SQL查询相关信息的解决方法,也可以使用10046、trace等方法实现。至于用那种方法好,见仁见智。

Howto Find which Session is Holding a Particular Library Cache Lock [ID 122793.1]

Troubleshooting Details

CommonSituations 

  • A DML operation that is hanging because the table which is accessed is currently undergoing changes (ALTER TABLE). This may take quite a long time depending on the size of the table and the type of the modification (e.g. ALTER TABLE x MODIFY (col1 CHAR(200) on a table with thousands of records)

Inthis case, V$LOCK will show that the session doing the 'ALTER TABLE' with anexclusive DML enqueue lock on the table object (LMODE=6, TYPE=TM where ID1 isthe OBJECT_ID of the table). The waiting session however does not show up inV$LOCK yet so in an environment with a lot of concurrent sessions the V$LOCKinformation will be insufficient to track down the culprit blocking youroperation.

  • The compilation of package will hang on Library Cache Lock and Library Cache Pin if any users are executing a procedure/function defined in the same package.

Method1: Systemstate Analysis

Systemstate event willcreate a tracefile containing detailed information on every Oracle process.This information includes all the resources held & requested by a specificprocess.

While an operation is hanging, open a new session and launch the followingstatement:

For Oracle 9.2.0.1 or higher:

$sqlplus '/ as sysdba'
oradebug setmypid
oradebug unlimit
oradebug dump systemstate266

For older versions you can use the following syntax that is also possible inhigher versions.The level 266 is not available before 9.2.0.6

alter session setmax_dump_file_size=unlimited;
alter session set events'immediate trace name systemstate level 10'

Oracle will create a systemstate tracefile in your USER_DUMP_DESTdirectory.

Get the PID (ProcessID) of the 'hanging' session:

select pid from v$process where addr=
(select paddr fromv$session where sid= <sid_of_hanging_session> );

The systemstate dump contains a separate section with information for eachprocess.
Open the tracefile and do a search for "PROCESS <PID fromabove>".
In the process section search for the wait event by doing a search on 'waitingfor'.

PROCESS20: 
---------------------------------------- 
SO: 0x7d2bd820, type: 2, owner: (nil), flag: INIT/-/-/0x00 
(process) Oracle pid=20, calls cur/top: 0x7d3d62d0/0x7d3d85dc, flag: (0) - 
int error: 0, call error: 0, sess error: 0, txn error 0 
(post info) last post received: 109 0 4 
last post received-location: kslpsr 
last process to post me: 7d2b8d94 1 6 
last post sent: 0 0 24 
last post sent-location: ksasnd 
last process posted by me: 7d2b8d94 1 6 
(latch info) wait_event=0 bits=0 
Process Group: DEFAULT, pseudo proc: 0x7d2ed5dc 
O/S info: user: oracle, term: pts/7, ospid: 19759 
OSD pid info: Unix process pid: 19759, image: goblin.forgotten.realms (TNSV1-V3)

<cut>

(session) sid: 141 trans: (nil), creator: 0x7d2bd820, flag: (41) USR/-BSY/-/-/-/-/-
DID: 0001-0014-00000668, short-term DID: 0000-0000-00000000 
txn branch: (nil) 
oct: 6, prv: 0, sql: 0x62d01c34, psql: 0x7c20f24c, user: 542/SCOTT 
service name: SYS$USERS 
O/S info: user: oracle, term: pts/7, ospid: 19758, machine:goblin.forgotten.realms
program: sqlplus@goblin.forgotten.realms (TNS V1-V3) 
application name: SQL*Plus, hash value=3669949024 
waiting for 'library cache lock' blocking sess=0x(nil) seq=36 wait_time=0seconds since wait started=11
handle address=62d064dc, lockaddress=79f88a68, 100*mode+namespace=c9

  • Use the handle address to find information on the object locked:

SO: 0x79f88a68, type: 53,owner: 0x7d3d62d0, flag: INIT/-/-/0x00
LIBRARY OBJECT LOCK: lock=79f88a68 handle=62d064dc request=S
call pin=(nil) session pin=(nil) hpc=0000 hlc=0000
htl=0x79f88ab4[0x79e71e60,0x79e71e60] htb=0x79e71e60 ssga=0x79e716fc
user=7d3a13b8 session=7d3a13b8 count=0 flags=[0000] savepoint=0xce
LIBRARY OBJECT HANDLE: handle=62d064dc mtx=0x62d06590(0) cdp=0
name=SCOTT.EMPLOYEES

We see the library object lock is being requested in Shared mode (request=S)
Name of the the object is SCOTT.EMPLOYEES

  • Use the 'handle address' to find the process that is holding the lock on  your resource by doing a search on the address within the same tracefile.

PROCESS 18: 
---------------------------------------- 
SO: 0x7d2bcca8, type: 2, owner: (nil), flag: INIT/-/-/0x00 
(process) Oracle pid=18, calls cur/top: 0x79f3ab84/0x7d3d5fc8, flag: (0) - 
int error: 0, call error: 0, sess error: 0, txn error 0 
(post info) last post received: 109 0 4 
last post received-location: kslpsr 
last process to post me: 7d2b8d94 1 6 
last post sent: 0 0 24 
last post sent-location: ksasnd 
last process posted by me: 7d2b8d94 1 6

<cut>

SO: 0x75fe8f7c, type: 53, owner: 0x7b751914, flag: INIT/-/-/0x00 
LIBRARY OBJECT LOCK: lock=75fe8f7c handle=62d064dc mode=X
call pin=(nil) session pin=(nil) hpc=0000 hlc=0000 
htl=0x75fe8fc8[0x79f81790,0x79fc3ef8] htb=0x79f81790 ssga=0x79f8102c 
user=7d3988d0 session=7d3988d0 count=1 flags=[0000] savepoint=0x146e 
LIBRARY OBJECT HANDLE: handle=62d064dc mtx=0x62d06590(0) cdp=0 
name=SCOTT.EMPLOYEES

From the output we can see that the Process 18 (pid)  is holding  anexclusive lock (mode=X) on the object we are trying to access. Using V$PROCESSand V$SESSION we can retrieve the sid, user, terminal, program,... for thisprocess.
 
The actual statement that was launched by this session is also listed in thetracefile (statements and other library cache objects are preceded by 'name=').

METHOD 2: EXAMINE THE X$KGLLK TABLE

TheX$KGLLK table (accessible only as SYS/INTERNAL) contains all the library objectlocks (both held & requested) for all sessions and is more complete thanthe V$LOCK view although the column names don't always reveal their meaning.

You can examine the locks requested (and held) by the waiting session bylooking up the session address (SADDR) in V$SESSION and doing the followingselect:

select sid,saddr fromv$session where event= 'library cache lock';

SID SADDR
---------- --------
16 572ed244

selectkgllkhdl Handle,kgllkreq Request, kglnaobj Object
fromx$kgllk where kgllkses = '572ed244'
andkgllkreq > 0;

HANDLE   REQUEST  OBJECT
-------- ----------------------------------------------------------------------
62d064dc         2 EMPLOYEES

This will show you the library cache lock requested by this session (KGLLKREQ> 0) where KGLNAOBJ contains the first 80 characters of the name of theobject.The value in KGLLKHDL corresponds with the 'handle address' of theobject in Method 1 Systemstate Analysis as shown above.

If we now match the KGLLKHDL with the handles of other sessions inX$KGLLK that should give us the address of the blocking session.The sessionholding the lock will have KGLLKMOD > 0 as it is holding the lock.

select kgllksessaddr,kgllkhdl handle,kgllkmod mod,kglnaobj object
fromx$kgllk lock_a
wherekgllkmod > 0
andexists (select lock_b.kgllkhdl from x$kgllk lock_b
wherekgllkses = '572ed244' /* blocked session */
andlock_a.kgllkhdl = lock_b.kgllkhdl
andkgllkreq > 0);

SADDR    HANDLE   MOD
--------  ------------------
OBJECT
------------------------------------------------------------
572eac94 62d064dc          3
EMPLOYEES

If we look a bit further we can then again match KGLLKSES with SADDR inv$session to find further information on the blocking session:

selectsid,username,terminal,program from v$session where saddr = '572eac94'

SID       USERNAME                 TERMINAL
---------------------------------------- ------------------------------
PROGRAM
------------------------------------------------
12         SCOTT                         pts/20
sqlplus@goblin.forgotten.realms(TNS V1-V3)

In the same way we can also find all the blocked sessions:

selectsid,username,terminal,program from v$session
wheresaddr in 
(selectkgllkses from x$kgllk lock_a 
 wherekgllkreq > 0
 andexists (select lock_b.kgllkhdl from x$kgllk lock_b
            where kgllkses = '572eac94' /* blocking session */
            and lock_a.kgllkhdl = lock_b.kgllkhdl
            and kgllkreq = 0)
);

SID      USERNAME                      TERMINAL
---------- ------------------------------------------------------------
PROGRAM
------------------------------------------------
13        SCOTT                          pts/22
sqlplus@goblin.forgotten.realms(TNS V1-V3)

16        SCOTT                          pts/7
sqlplus@goblin.forgotten.realms(TNS V1-V3)


Related Documents

Note:1020008.6 SCRIPT FULLY DECODED LOCKING SCRIPT
Note:1054939.6 COMPILATION OF PACKAGE IS HANGING ONLIBRARY CACHE LOCK

=================
library cache pin
=================
原理
~~~~~
An Oracle instance has alibrary cache that contains the description of  
different types of objectse.g. cursors, indexes, tables, views, procedures,  
... Those objects cannot bechanged when they are used. They are locked by a  
mechanism based on librarylocks and pins. A session that need to use an object  
will first acquire a librarylock in a certain mode (null, shared or exclusive)  
on the object, in order toprevent other sessions from accessing the same  
object (e.g. exclusive lockwhen recompiling a package or view) or to maintain  
the object definition for along time. Locking an object is sometimes referred 
as the job to locate it inthe library cache and lock it in a certain mode. 
If the session wants tomodify or examine the object, it must acquire after  
the lock also a pin in acertain mode (again null, shared or exclusive).

Each SQL statement that wantto use/modify objects that are locked or pinned  
and whose lock/pin mode isincompatible with the requested mode, will wait  
on events like 'library cachepin' or 'library cache lock' until a timeout  
occurs. The timeout normallyoccurs after 5 minutes and the SQL statement  
then ends with an ORA-4021.If a deadlock is detected, an ORA-4020 is given  
back.

Dealing with slow downsrelated to "mysterious" library cache pins  
and load locks we should lookfor the reason of the database object  
invalidations. They arelikely to be triggered by actions causing  
changes to"LAST_DDL" attribute of database objects that have other 
dependent ones. Typicallythey are the object maintenance operations -  
ALTER, GRANT, REVOKE,replacing views, etc. This behavior is described 
in Oracle Server ApplicationDeveloper's Guide as object dependency 
maintenance.

After object invalidation,Oracle tries to recompile the object at the 
time of the first access toit. It may be a problem in case when other 
sessions have pinned theobject to the library cache. It is obvious that 
it is more likely to occurwith more active users and with more complex 
dependencies (eg. manycross-dependent packages or package bodies).  
In some cases waiting forobject recompilation may even take hours  
blocking all the sessionstrying to access it.

ORA-04021 timeout occurredwhile waiting to lock object %s%s%s%s%s". 
Cause:  Whiletrying to lock a library object, a time-out occurred. 
Action: Retry the operationlater.

ORA-04020 deadlock detectedwhile trying to lock object %s%s%s%s%s 
Cause:  Whiletrying to lock a library object, a deadlock is detected. 
Action: Retry the operationlater. 
(see <Note.166924.1>)

2.   Which viewscan be used to detect library locking problems? 
----------------------------------------------------------------

Different views can be usedto detect pin/locks:

DBA_KGLLOCK : one row foreach lock or pin of the instance 
-KGLLKUSE  sessionaddress 
-KGLLKHDL  Pin/Lockhandle 
-KGLLKMOD/KGLLKREQ  Holding/requestedmode 
0          no lock/pin held 
1          null mode 
2          share mode 
3          exclusive mode 
-KGLLKTYPE Pin/Lock 
(created via the $ORACLE_HOME/rdbms/admin/catblock.sql)

V$ACCESS : one row for eachobject locked by any user 
-SID      session sid 
-OWNER    username 
-OBJECT    objectname 
-TYPE     object type

V$DB_OBJECT_CACHE : one rowfor each object in the library cache 
-OWNER        object owner 
-NAME         object name or cursor text 
-TYPE         object type 
-LOCKS        number of locks on this object 
-PINS         number of pins on this object

DBA_DDL_LOCKS  :one row for each object that is locked (exception made of the cursors) 
-SESSION_ID 
-OWNER 
-NAME 
-TYPE 
-MODE_HELD 
-MODE_REQUESTED

V$SESSION_WAIT : each sessionwaiting on a library cache pin or lock is blocked by some other session 
-p1 = object address 
-p2 = lock/pin address

3.   How to findout why an ORA-4021 occurs? 
--------------------------------------------

When you execute thestatement that generates the ORA-4021, it is possible  
during the delay of 5 minutesto detect the reason for the blocking situation.  
Following query can be usedto find the blocking and waiting sessions:

FYI: You need to run thescript called "catblock.sql" first.  
===  This scriptcan be found in:  $ORACLE_HOME/rdbms/admin/catblock.sql

select /*+ ordered */w1.sid  waiting_session, 
        h1.sid  holding_session, 
       w.kgllktype lock_or_pin, 
       w.kgllkhdl address, 
       decode(h.kgllkmod,  0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive', 
          'Unknown') mode_held,  
       decode(w.kgllkreq,  0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive', 
          'Unknown') mode_requested 
  from dba_kgllockw, dba_kgllock h, v$session w1, v$session h1 
where 
  (((h.kgllkmod !=0) and (h.kgllkmod != 1) 
     and((h.kgllkreq = 0) or (h.kgllkreq = 1))) 
   and 
    (((w.kgllkmod = 0) or (w.kgllkmod= 1)) 
     and((w.kgllkreq != 0) and (w.kgllkreq != 1)))) 
  and  w.kgllktype        =  h.kgllktype 
  and  w.kgllkhdl        =  h.kgllkhdl 
  and  w.kgllkuse    =   w1.saddr 
  and  h.kgllkuse    =   h1.saddr 
/

The result looks like:

WAITING_SESSIONHOLDING_SESSION LOCK ADDRESS  MODE_HELD MODE_REQU 
------------------------------ ---- -------- --------- --------- 
            16             12 Pin  03FA2270 Share    Exclusive

The object that is locked canbe found with v$object_dependency and  
should be the same as the onementioned in the ORA-4021 error message. 
e.g. 
select to_name fromv$object_dependency where to_address = '03FA2270'; 
should give:

TO_NAME 
------------- 
DBMS_PIPE

You can find which library objectsare used by each session via following  
queries, e.g.  
a. for the blocked session:

select distinct kglnaobj fromx$kgllk  where  
kgllkuse in (select saddrfrom v$session where sid = 16);

b. for the blocking session

select distinct kglnaobj fromx$kgllk  where  
kgllkuse in (select saddrfrom v$session where sid = 12);

One of those objects can bethe cursor or statement that each session is  
executing/trying to execute.

You can also use the$ORACLE_HOME/rdbms/admin/utldtree.sql utility to find out  
how the dependency tree lookslike and which objects are dependent on e.g.  
DBMS_PIPE. One of thoseobjects will be the sql statement of the holding  
session. A variant script onutldtree.sql stands in [NOTE:139594.1] and  
gives which objects an objectdepends on.

Library cache pins are used to manage library cacheconcurrency. 
       Pinning an object causes the heaps to be loaded into memory(if not already loaded).
       PINS can be acquired in NULL, SHARE or EXCLUSIVE modes andcan be considered like a special form of lock. 
       A wait for a "library cache pin" implies some othersession holds that PIN in an incompatible mode. 
       
       P1 = Handle address 
       P2 = Pin address 
       P3 = Encoded Mode & Namespace 
       
       ·Handle address
       ~~~~~~~~~~~~~~~~                                                                                      
       Use P1RAW rather than P1                                                                                    
       This is the handle of the library cache object which thewaiting session wants to acquire a pin on.

查找library cache对象
~~~~~~~~~~~~~~  
       The actual object being waited on can be found using                                                        
         SELECT kglnaown "Owner", kglnaobj"Object"                                                                 
           FROM x$kglob                                                                                            
          WHERE kglhdadr='&1RAW'                                                                                  
         ;                                                                                                        
       ·Pin address
       ~~~~~~~~~~~~~
       Use P2RAW rather than P2                                                                                    
       This is the address of the PIN itself.                                                                       
       ·Encoded Mode & Namespace                                                                            
       ~~~~~~~~~~~~~~~~~~~~~~~~~
       In Oracle 7.0 - 8.1.7 inclusive the value is 10 * Mode +Namespace.                                            
       In Oracle 9.0 - 9.2 inclusive the value is 100 * Mode +Namespace.                                             
                                                                                                                  
       Where:                                                                                                     
                                                                                                                  
       Mode is the mode in which the pin is wanted. This is a numberthus:                                            
       o        2 - Share mode                                                                                      
       o        3 - Exclusive mode                                                                                  
                                                                                                                  
       Namespace is just the namespace number of the namespace inthe library cache in which the required object lives: 
       o        0 SQL Area                                                                                          
       o        1 Table / Procedure / Function /Package Header                                                       
       o        2 Package Body                                                                                      
       o        3 Trigger                                                                                           
       o        4 Index                                                                                            
        o       5 Cluster                                                                                           
       o        6 Object                                                                                            
       o        7 Pipe                                                                                             
       o        13 Java Source                                                                                      
       o        14 Java Resource                                                                                    
       o        32 Java Data        

====================
library cache lock的成因和解决方法
====================
两种原因
~~~~~~~~~
* a DML operation that ishanging because the table which is accessed is currently  
   undergoingchanges (ALTER TABLE). This may take quite a long time depending on  
   the size of thetable and the type of the modification  
   (e.g. ALTERTABLE x MODIFY (col1 CHAR(200) on thousands of records).

* The compilation of packagewill hang on Library Cache Lock and Library Cache Pin  
  if some users areexecuting any Procedure/Function defined in the same package.

两种解决办法
~~~~~~~~~~~~~~~
METHOD 1: SYSTEMSTATEANALYSIS 
------------------------------

One way of finding thesession blocking you is to analyze the system state dump. 
Using the systemstate eventone can create a tracefile containing detailed  
information on every Oracleprocess. This information includes all the resources 
held & requested by aspecific process.

Whilst an operation ishanging, open a new session and launch the following 
statement:

ALTER SESSION SET EVENTS'IMMEDIATE TRACE NAME SYSTEMSTATE LEVEL 8';

Oracle will now create asystemstate tracefile in your USER_DUMP_DEST directory. 
Get the PID (ProcessID) ofthe 'hanging' session from the V$PROCESS by matching  
PADDR from V$SESSION withADDR from V$PROCESS:

SELECT PID FROM V$PROCESSWHERE ADDR= 
       (SELECT PADDR FROM V$SESSION WHERE SID=sid_of_hanging_session);

The systemstate dump containsa separate section with information for each  
process. Open the tracefileand do a search for 'PROCESS pid_from_select_stmt'. 
In the process section lookup the wait event by doing a search on 'waiting for'.

Example output:

PROCESS 8: 
  ---------------------------------------- 
   SO: 50050b08,type: 1, owner: 0, flag: INIT/-/-/0x00 
   (process) Oraclepid=8, calls cur/top: 5007bf6c/5007bf6c, flag: (0) - 
            int error: 0, call error: 0, sess error: 0,txn error 0 
   (post info) lastpost received: 82 0 4 
              last post received-location:kslpsr 
              last process to post me: 5004ff081 2 
              last post sent: 0 0 13 
              last post sent-location: ksasnd 
              last process posted by me:5004ff08 1 2 
    (latch info) wait_event=0 bits=0 
    Process Group: DEFAULT, pseudo proc: 50058ac4 
     O/Sinfo: user: daemon, term: pts/1, ospid: 15161 
     OSDpid info: 15161 
    ---------------------------------------- 
     SO:5005f294, type: 3, owner: 50050b08, flag: INIT/-/-/0x00 
    (session) trans: 0, creator: 50050b08, flag: (41) USR/-BSY/-/-/-/-/- 
              DID: 0001-0008-00000002,short-term DID: 0000-0000-00000000 
              txn branch: 0 
              oct: 6, prv: 0, user: 41/LC 
     O/Sinfo: user: daemon, term: pts/1, ospid: 15160, machine: goblin.forgotten.realms 
              program: sqlplus@goblin.forgotten.realms (TNS V1-V3) 
    application name: SQL*Plus, hash value=3669949024 
    waiting for 'library cache lock' blocking sess=0x0 seq=253wait_time=0  --等待事件,seq次数,
!>>             handle address=5023ef9c, lockaddress=5019cad4, 10*mode+namespace=15

Using the 'handle address'you can look up the process that is keeping a lock 
on your resource by doing asearch on the address within the same tracefile.

Example output:

PROCESS 9: 
  ---------------------------------------- 
   SO: 50050e08,type: 1, owner: 0, flag: INIT/-/-/0x00 
   (process) Oraclepid=9, calls cur/top: 5007bbac/5007bbfc, flag: (0) - 
            int error: 0, call error: 0, sess error: 0,txn error 0 
  
   <cut> .... 
   
       ---------------------------------------- 
        SO: 5019d5e4, type: 34, owner: 5015f65c, flag: INIT/-/-/0x00 
!>>     LIBRARY OBJECT PIN: pin=5019d5e4 handle=5023ef9c mode=Xlock=0  --handle address
        user=5005fad4 session=5005fad4 count=1 mask=0511savepoint=118218 flags=[00] 
   
From the output we can seethat the Oracle process with PID 9 has an exclusive 
lock on the object we aretrying to access. Using V$PROCESS and V$SESSION we can 
retrieve thesid,user,terminal,program,... for this process. The actual statement 
that was launched by thissession is also listed in the tracefile (statements and 
other library cache objectsare preceded by 'name=').

METHOD 2: EXAMINE THE X$KGLLKTABLE 
-----------------------------------

The X$KGLLK table (accessibleonly as SYS/INTERNAL) contains all the  
library object locks (bothheld & requested) for all sessions and 
is more complete than theV$LOCK view although the column names don't 
always reveal their meaning.

You can examine the locksrequested (and held) by the waiting session  
by looking up the sessionaddress (SADDR) in V$SESSION and doing the  
following select:

select * from x$kgllk whereKGLLKSES = 'saddr_from_v$session'

This will show you all thelibrary locks held by this session where 
KGLNAOBJ contains the first80 characters of the name of the object. 
The value in KGLLKHDLcorresponds with the 'handle address' of the 
object in METHOD 1.

You will see that at leastone lock for the session has KGLLKREQ > 0  
which means this is a REQUESTfor a lock (thus, the session is waiting).  
If we now match the KGLLKHDLwith the handles of other sessions in  
X$KGLLK that should give usthe address of the blocking session since 
KGLLKREQ=0 for this session,meaning it HAS the lock. 
  
SELECT * FROM X$KGLLKLOCK_A  
WHERE KGLLKREQ = 0 
   AND EXISTS(SELECT LOCK_B.KGLLKHDL FROM X$KGLLK LOCK_B 
              WHERE KGLLKSES ='saddr_from_v$session' /* BLOCKED SESSION */ 
              AND LOCK_A.KGLLKHDL =LOCK_B.KGLLKHDL 
              AND KGLLKREQ > 0);

If we look a bit further wecan then again match KGLLKSES with SADDR  
in v$session to find furtherinformation on the blocking session:

SELECTSID,USERNAME,TERMINAL,PROGRAM FROM V$SESSION 
WHERE SADDR in  
  (SELECT KGLLKSESFROM X$KGLLK LOCK_A  
   WHERE KGLLKREQ =0 
     ANDEXISTS (SELECT LOCK_B.KGLLKHDL FROM X$KGLLK LOCK_B 
                WHERE KGLLKSES ='saddr_from_v$session' /* BLOCKED SESSION */ 
                AND LOCK_A.KGLLKHDL =LOCK_B.KGLLKHDL 
                AND KGLLKREQ > 0) 
  );

In the same way we can alsofind all the blocked sessions:

SELECTSID,USERNAME,TERMINAL,PROGRAM FROM V$SESSION 
WHERE SADDR in  
  (SELECT KGLLKSESFROM X$KGLLK LOCK_A  
   WHERE KGLLKREQ> 0 
     ANDEXISTS (SELECT LOCK_B.KGLLKHDL FROM X$KGLLK LOCK_B 
                WHERE KGLLKSES ='saddr_from_v$session' /* BLOCKING SESSION */ 
                AND LOCK_A.KGLLKHDL =LOCK_B.KGLLKHDL 
                AND KGLLKREQ = 0) 
  );

 

 

---本文是网络资料加metalink 等整理得来