🔍 核心原因:DDL锁冲突
当你要编译(ALTER)一个存储过程时,Oracle需要给它加上一个排他DDL锁(Exclusive DDL Lock) -2-9。如果这时有其他会话正在执行 或修改 同一个存储过程,或者是这个存储过程正在被调试 ,Oracle就会因为无法获得这个排他锁而导致编译操作被挂起或超时-2-10。
🛠️ 解决步骤:定位并杀掉阻塞会话
以下是标准的排查与解决流程:
第一步:查找锁住的对象
首先,查询V$DB_OBJECT_CACHE视图,确认你的存储过程是否确实被锁,以及锁的数量-2-3-4。把YOUR_PROC_NAME换成你的存储过程名(注意用大写)。
sql
复制
下载
SELECT * FROM V$DB_OBJECT_CACHE
WHERE name = 'YOUR_PROC_NAME' AND LOCKS != '0';
如果查询有结果且LOCKS大于0,就说明确实被锁了。
第二步:找出阻塞会话的SID
通过V$ACCESS视图,找出是哪个会话(SID)锁住了这个对象-2-3-4。
sql
复制
下载
SELECT /*+ rule */ SID FROM V$ACCESS
WHERE object = 'YOUR_PROC_NAME';
记下这里查出来的SID。
第三步:获取会话的SERIAL#
根据上一步得到的SID,查询V$SESSION视图获取对应的SERIAL#,杀掉会话时这两个信息都需要-2-3-4。
sql
复制
下载
SELECT SID, SERIAL#, PADDR FROM V$SESSION
WHERE SID = '刚才查到的SID';
第四步:杀掉阻塞会话
拥有SID和SERIAL#后,就可以执行命令强制结束这个会话,释放它占用的锁-2-3-4。
sql
复制
下载
ALTER SYSTEM KILL SESSION 'sid值, serial#值' IMMEDIATE;
成功执行这个命令后,再尝试编译你的存储过程,应该就可以了
SELECT * FROM V$DB_OBJECT_CACHE
WHERE name = 'ZZTEST' AND LOCKS != '0';
SELECT /*+ rule */ SID FROM V$ACCESS
WHERE object = 'ZZTEST';
SELECT SID, SERIAL#, PADDR FROM V$SESSION
WHERE SID = '2269';
ALTER SYSTEM KILL SESSION '2269, 15933' IMMEDIATE;