存储过程存在DDL锁时能否编译?编译无响应且未查到阻塞会话怎么办?
存储过程/函数DDL锁与编译问题解答
存在DDL锁时能否编译?
当存储过程或函数上持有DDL锁时,无法对其执行编译操作。编译本质上属于DDL操作,需要修改对象的元数据,而DDL锁(尤其是排他型DDL锁,如LOCK TABLE ... IN EXCLUSIVE MODE或对象级排他锁)会阻止任何对该对象的修改请求,编译请求会被直接阻塞,直到锁被释放。
编译无反应但未查到阻塞会话的排查方向
如果执行编译后无任何反馈,且通过v$session未查到blocking_session,可以从以下几个方向排查:
直接检查目标对象的锁信息
不要局限于会话阻塞查询,直接查询存储过程/函数上的锁:SELECT l.session_id, l.oracle_username, l.locked_mode, o.object_name, o.object_type FROM v$locked_object l JOIN dba_objects o ON l.object_id = o.object_id WHERE o.object_type IN ('PROCEDURE', 'FUNCTION') AND o.object_name = '你的存储过程/函数名';若
locked_mode为6(排他锁),说明该对象被持有DDL锁,会阻塞编译操作。排查依赖对象的锁与未提交事务
存储过程编译时需要验证所有依赖对象的元数据,如果依赖的表/视图存在长时间未提交的DML事务,可能间接阻塞编译。可以查询依赖对象的锁状态:SELECT s.sid, s.serial#, s.status, s.sql_id, l.locked_mode, o.object_name FROM v$session s JOIN v$locked_object l ON s.sid = l.session_id JOIN dba_objects o ON l.object_id = o.object_id WHERE o.object_name IN (SELECT referenced_name FROM dba_dependencies WHERE name = '你的存储过程/函数名');查看编译会话的等待事件
检查执行编译操作的当前会话正在等待的资源,判断阻塞原因:SELECT s.sid, s.event, s.wait_time, s.seconds_in_wait FROM v$session s WHERE s.sql_text LIKE '%ALTER PROCEDURE%' OR s.sql_text LIKE '%ALTER FUNCTION%';常见的等待事件如
library cache lock、row cache lock,可以帮你定位是数据字典还是共享库缓存的问题。检查依赖对象的有效性
如果存储过程依赖的对象处于无效状态,或存在循环依赖,编译过程可能卡住。查询依赖对象的状态:SELECT referenced_name, referenced_type, status FROM dba_dependencies d JOIN dba_objects o ON d.referenced_name = o.object_name WHERE d.name = '你的存储过程/函数名';先修复所有无效的依赖对象,再尝试编译目标存储过程/函数。
内容的提问来源于stack exchange,提问作者DIPAK SHAH
相关产品推荐
相关产品推荐

