oracle分区表ddl触发全局library cache lock,因其以mode=3独占锁定整表对象句柄(kglhdnsp=1),而非仅分区元数据;因分区表在library cache中为单一table对象,ddl需确保所有依赖sql/plsql与新分区布局一致,故必须失效并重载整个对象。
分区表ddl为什么触发全局library cache lock
因为oracle对分区表执行alter table ... add partition、exchange partition等操作时,会以独占模式(mode=3)在library cache中锁定整个表对象句柄,而不仅是分区元数据。这个锁会阻塞所有依赖该表的sql解析、pl/sql执行、甚至desc命令——只要涉及该表名,就会等待library cache lock。
为什么不是只锁分区,而是锁整张表
Oracle的Library Cache锁粒度基于对象句柄(handle),不是物理结构。分区表在Library Cache中仍是一个TABLE/PROCEDURE类型的单一对象(KGLHDNSP=1),其所有分区共享同一个句柄。DDL修改分区结构时,必须确保:当前所有已加载的SQL计划、包体、视图定义都与新分区布局一致,所以必须先失效并重载整个对象——这就要求排他锁。
- 即使只加一个分区,
v$db_object_cache中该表的locks字段也会变为非零 -
SELECT * FROM v$lock WHERE type='KGL'会显示lmode=3(Exclusive)且id1指向该表句柄地址 - RAC环境下,这个锁还会触发
DFS lock handle跨节点同步,放大等待链
大规模分区DDL后实例Hang的直接诱因
当几万次分区DDL在短时间内密集执行(如按月批量维护分区表),Shared Pool中大量句柄反复加锁/释放,导致:内存碎片加剧、Library Cache Pin争用激增、ASH中library cache lock采样占比飙升——最终表现为会话卡在WAITING或ON CPU但无实际进展,v$session里blocking_session指向正在编译的DDL会话,而它自己又卡在DFS lock handle上。
- 补丁
11.2.0.3.7之前,RAC节点间锁协调效率低,容易形成死锁式等待环 -
TRUNCATE PARTITION比DROP PARTITION更危险:前者隐含DDL+高水位重置,持锁时间更长 - 若DDL中途被中断(如客户端断开),句柄锁可能残留数小时,
v$locked_object查不到,但x$kglpn里kglpnmod=3仍在
怎么确认是不是分区DDL引发的锁
别只盯着v$session_wait,直接查ASH中锁源头:
SELECT sql_id, sql_opname, event, p1text, p1, blocking_session, session_state
FROM gv$active_session_history
WHERE event = 'library cache lock'
AND sample_time > SYSDATE - 1/24
AND sql_opname IN ('ALTER', 'CREATE', 'DROP')
AND p1text = 'handle address'
AND EXISTS (
SELECT 1 FROM v$db_object_cache c
WHERE c.addr = RAWTOHEX(p1)
AND c.type = 'TABLE'
AND c.name LIKE '%PARTITION%'
);
- 如果
sql_text含ADD PARTITION、EXCHANGE PARTITION或表名带_P202606类分区标识,基本坐实 -
p2text='lock address'对应x$kgllk.kgllkhdl,可进一步关联v$object_dependency看哪些包/视图依赖该表 - RAC环境务必用
gv$视图,单查v$会漏掉另一节点的持锁会话
真正麻烦的不是锁本身,而是锁住之后其他会话不断尝试解析同一SQL,把Shared Pool撑满、触发cursor: pin S wait on X连锁反应——这时候kill会话只是延缓崩溃,不解决根本的句柄争用。











