最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何解决Oracle存储过程中的死锁问题?
时间:2026-08-10 10:27:49 编辑:袖梨 来源:一聚教程网
查v$locked_object无结果但业务卡死,大概率是普通锁等待或事务未提交;应先查gv$session中status='ACTIVE'且event含'enq: TX%'的会话定位真实阻塞源,再结合v$sql和v$transaction确认是否自持锁未提交,而非盲目kill。
查v$locked_object没结果,但业务卡死怎么办
不是所有卡顿都是死锁,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里
存储过程里写UPDATE,为什么容易触发死锁
存储过程本身不导致死锁,但它的执行模式放大了风险:隐式事务边界模糊、SQL执行顺序不可控、异常路径缺少ROLLBACK。比如两个过程分别按不同顺序更新table_a和table_b,就极易形成A→B→A循环等待。
- 避免在存储过程中拼接动态SQL做DML,尤其跨表操作——静态SQL+明确提交点更可控
- 所有DML后必须显式
COMMIT或ROLLBACK,不能依赖调用方;异常分支里漏写ROLLBACK是高频坑 - 批量更新用
FORALL替代游标循环,减少锁持有时间;单条UPDATE尽量带WHERE条件缩小锁范围
alter system kill session 'sid,serial#' 为什么没立刻生效
这条命令只是标记会话为终止状态,不是立即断开连接。status变成'KILLED'后,会话仍在清理undo、释放资源,客户端可能持续看到ORA-00028长达数秒甚至更久。
- 加
IMMEDIATE参数强制中断:ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE(12c+稳定支持) - RAC环境必须指定实例号:
ALTER SYSTEM KILL SESSION '123,456,@2',否则可能在错误节点执行 - kill前先查
v$transaction确认used_ublk是否归零,未归零说明事务还在回滚中,硬杀可能延长恢复时间
ORA-00060报错后,为什么查不到活跃死锁
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。
相关文章
- 突发|OpenAI紧急暂缓自家最强模型Astra 08-10
- 学历提升报名入口官网-学历提升报名官网 08-10
- 寒武纪2026年上半年业绩亮眼 营收接近翻倍增长 08-10
- 原神2026年海灯节福利介绍汇总 08-10
- 不挂科在线搜题网页版官方入口最新链接 08-10
- 摩尔线程上半年营收大幅增长147.42%,S5000智算集群实现规模化销售 08-10