为什么会发生 ora-4021 错误?
oracle 实例包含一个cache缓存,用于保存每种不同类型的对象(例如游标、索引、表、视图、过程等)的定义。此缓存称为library cache库缓存,包含对象定义的"library库"。当这些对象正在使用时,无法更改这些定义。它们由一系列称为library cache lock和
library cache pin的锁进行保护。
需要使用对象的会话将首先尝试在对象(空、共享或独占)上以特定模式获取库锁。如果它获得库缓存锁,这将阻止其他会话修改它(例如,在重新编译包或视图时将采用独占锁)。如果锁不可用,它将等到它可以获得它(即当另一个会话停止使用它时)。锁定对象是第一步,本质上是在库缓存中找到对象,然后将其锁定在特定模式下的任务。如果会话想要修改或检查对象,它还必须在锁定后以特定模式(同样为空、共享或独占)获取pin。
每个想要使用/修改已锁定或固定的对象(并且其锁定/固定模式与请求的模式不兼容)的 sql 语句都将等待"library cache pin"或"library cache lock"等事件,直到它被释放,并且它可以获取锁定。如果它等待的时间超过预定义的阈值(实例个数*5分钟),则会发生超时。这样做是为了释放等待会话中可能阻止其他会话的资源,而不是具有一系列无法移动的会话。
如果超时,则会引发 ora-4021 错误
如何诊断?
先执行脚本
-
$oracle_home/rdbms/admin/catblock.sql
再复现引起问题的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_kgllock w, 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
-
/
然后通过 v$object_dependency 关联 address
-
select to_name from v$object_dependency where to_address = '03fa2270';
查看等待者
-
select distinct kglnaobj from x$kgllk where
-
kgllkuse in (select saddr from v$session where sid = 16);
查看持有者
-
select distinct kglnaobj from x$kgllk where
-
kgllkuse in (select saddr from v$session where sid = 12);
参考:如何分析库缓存超时与关联: ora-04021"等待锁定对象 %s%s%s%s%s 时超时发生"错误 (文档 id 1486712.1)
阅读(1067) | 评论(0) | 转发(0) |