查v$locked_object无结果但业务卡死,大概率是普通锁等待或事务未提交;应先查gv$session中status='ACTIVE'且event含'enq: TX%'的会话定位真实阻塞源,再结合v$sql和v$transaction确认是否自持锁未提交,而非盲目kill。
不是所有卡顿都是死锁,v$locked_object为空时,大概率是普通锁等待或事务未提交。先别急着kill——status = 'ACTIVE'且event为enq: TX - row lock contention的会话,才是真正在等行锁;而status = 'INACTIVE'、lockwait为空、sql_id非空的会话,更可能是它自己持锁没提交。
SELECT sid, serial#, sql_id, event, blocking_session FROM gv$session WHERE status = 'ACTIVE' AND event LIKE 'enq: TX%'过滤出真实阻塞源(RAC必须用gv$)v$sql确认sql_text是否含未提交的UPDATE/DELETE,而不是只看program就杀LOCKWAIT字段为空≠没锁:Oracle在死锁发生后已自动回滚牺牲者,其lockwait会被清空,但sid仍留在v$locked_object里存储过程本身不导致死锁,但它的执行模式放大了风险:隐式事务边界模糊、SQL执行顺序不可控、异常路径缺少ROLLBACK。比如两个过程分别按不同顺序更新table_a和table_b,就极易形成A→B→A循环等待。
COMMIT或ROLLBACK,不能依赖调用方;异常分支里漏写ROLLBACK是高频坑FORALL替代游标循环,减少锁持有时间;单条UPDATE尽量带WHERE条件缩小锁范围这条命令只是标记会话为终止状态,不是立即断开连接。status变成'KILLED'后,会话仍在清理undo、释放资源,客户端可能持续看到ORA-00028长达数秒甚至更久。
IMMEDIATE参数强制中断:ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE(12c+稳定支持)ALTER SYSTEM KILL SESSION '123,456,@2',否则可能在错误节点执行v$transaction确认used_ublk是否归零,未归零说明事务还在回滚中,硬杀可能延长恢复时间ORA-00060只记录在alert log里,是历史事件快照,不是实时状态。Oracle检测到死锁后已自动处理(选一个会话回滚),此时阻塞链早已断裂,v$session里只剩“残局”。
ORA-00060日志,要结合gv$session和v$locked_object交叉验证当前是否存在阻塞链SELECT * FROM gv$session START WITH blocking_session IS NOT NULL CONNECT BY PRIOR sid = blocking_session
final_blocking_session字段(11gR2+启用_kill_blocker参数后可用)能直接定位最上层源头,比层层追溯更可靠真正难的不是找到谁被卡住,而是判断该不该杀、杀完会不会让应用重试逻辑反复触发相同锁竞争——这需要看sql_text上下文,而不是只看sid和program。