Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3567477
  • 博文数量: 715
  • 博客积分: 1860
  • 博客等级: 上尉
  • 技术积分: 7745
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-07 08:51
个人简介

偶尔有空上来看看

文章分类

全部博文(715)

文章存档

2023年(75)

2022年(134)

2021年(238)

2020年(115)

2019年(11)

2018年(9)

2017年(9)

2016年(17)

2015年(7)

2014年(4)

2013年(1)

2012年(11)

2011年(27)

2010年(35)

2009年(11)

2008年(11)

最近访客

分类: Oracle

2022-03-05 15:02:06

为什么会发生 ORA-4021 错误?
Oracle 实例包含一个cache缓存,用于保存每种不同类型的对象(例如游标、索引、表、视图、过程等)的定义。此缓存称为library cache库缓存,包含对象定义的"library库"。当这些对象正在使用时,无法更改这些定义。它们由一系列称为library cache lock和library cache pin的锁进行保护。

需要使用对象的会话将首先尝试在对象(空、共享或独占)上以特定模式获取库锁。如果它获得库缓存锁,这将阻止其他会话修改它(例如,在重新编译包或视图时将采用独占锁)。如果锁不可用,它将等到它可以获得它(即当另一个会话停止使用它时)。锁定对象是第一步,本质上是在库缓存中找到对象,然后将其锁定在特定模式下的任务。如果会话想要修改或检查对象,它还必须在锁定后以特定模式(同样为空、共享或独占)获取pin。

每个想要使用/修改已锁定或固定的对象(并且其锁定/固定模式与请求的模式不兼容)的 SQL 语句都将等待"library cache pin"或"library cache lock"等事件,直到它被释放,并且它可以获取锁定。如果它等待的时间超过预定义的阈值(实例个数*5分钟),则会发生超时。这样做是为了释放等待会话中可能阻止其他会话的资源,而不是具有一系列无法移动的会话。

如果超时,则会引发 ORA-4021 错误



如何诊断?


先执行脚本
  1. $ORACLE_HOME/rdbms/admin/catblock.sql

再复现引起问题的sql

然后执行下面的查询
  1. select /*+ ordered */ w1.sid waiting_session,
  2.          h1.sid holding_session,
  3.          w.kgllktype lock_or_pin,
  4.          w.kgllkhdl address,
  5.          decode(h.kgllkmod, 0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive',
  6.             'Unknown') mode_held,
  7.          decode(w.kgllkreq, 0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive',
  8.           'Unknown') mode_requested
  9.    from dba_kgllock w, dba_kgllock h, v$session w1, v$session h1
  10.   where
  11.    (((h.kgllkmod != 0) and (h.kgllkmod != 1)
  12.       and ((h.kgllkreq = 0) or (h.kgllkreq = 1)))
  13.     and
  14.       (((w.kgllkmod = 0) or (w.kgllkmod= 1))
  15.       and ((w.kgllkreq != 0) and (w.kgllkreq != 1))))
  16.    and w.kgllktype = h.kgllktype
  17.    and w.kgllkhdl = h.kgllkhdl
  18.    and w.kgllkuse = w1.saddr
  19.    and h.kgllkuse = h1.saddr
  20. /

然后通过 v$object_dependency 关联 ADDRESS
  1. select to_name from v$object_dependency where to_address = '03FA2270';

查看等待者
  1. select distinct kglnaobj from x$kgllk where
  2. kgllkuse in (select saddr from v$session where sid = 16);
查看持有者
  1. select distinct kglnaobj from x$kgllk where
  2. kgllkuse in (select saddr from v$session where sid = 12);

参考:如何分析库缓存超时与关联: ORA-04021"等待锁定对象 %s%s%s%s%s 时超时发生"错误 (文档 ID 1486712.1)


阅读(1164) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~