故障排查5 分钟阅读
Oracle 死锁 ORA-00060 排查与处理 — 完整实战指南
Oracle 死锁 ORA-00060 是生产环境高频问题。本文讲解死锁原理、Alert Log trace 分析、锁等待链查询、主动解除死锁的方法,附预防死锁的 SQL 编写规范。
2026年4月26日阅读—点赞—收藏—
oracle死锁ora-00060锁等待性能
在知识库中专注阅读,并随时返回相关工具与课程
Oracle 死锁 ORA-00060 是生产环境高频问题。本文讲解死锁原理、Alert Log trace 分析、锁等待链查询、主动解除死锁的方法,附预防死锁的 SQL 编写规范。
生产环境收到告警 ORA-00060: deadlock detected while waiting for resource——别慌,Oracle 会自动选择一个"牺牲者"回滚其事务。但如果死锁频繁发生,说明应用层存在设计问题,需要排查和优化。
死锁 = 两个(或多个)会话互相持有对方需要的锁,形成循环等待。
Session A: 锁住 Row 1 → 等待 Row 2 的锁 Session B: 锁住 Row 2 → 等待 Row 1 的锁 → 两者都无法继续 → 死锁
Oracle 的死锁检测器(约每 3 秒扫描一次)发现后,会选择一个 session 作为牺牲者,回滚该 session 的当前语句(注意:不是整个事务),并向其返回 ORA-00060。
Oracle 检测到死锁时,会自动生成一个 trace 文件,并在 Alert Log 中记录路径:
1# 查看 Alert Log 中的死锁记录23> **本章目标**:掌握本章核心知识点4> **前置要求**:完成前序章节学习5> **预计时长**:60 分钟67grep -A5 "ORA-00060" $ORACLE_BASE/diag/rdbms/orcl/orcl/trace/alert_orcl.log89# 输出类似:10# ORA-00060: Deadlock detected. More info in file11# /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_12345.trc1# 查看死锁的完整信息2cat /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_12345.trcTrace 文件中的关键信息:
1Deadlock graph:2 ---------Blocker-------- ---------Waiter---------3Resource Name process session holds waits process session holds waits4TX-00050017-00000456 22 137 X 23 189 X5TX-00060023-00000789 23 189 X 22 137 X如果死锁正在发生或怀疑有锁等待:
1-- 查看所有锁等待链2SELECT3 s1.sid || ',' || s1.serial# AS blocker,4 s1.username AS blocker_user,5 s1.sql_id AS blocker_sql,6 s2.sid || ',' || s2.serial# AS waiter,7 s2.username AS waiter_user,8 s2.sql_id AS waiter_sql,9 s2.seconds_in_wait AS wait_seconds10FROM v$session s111JOIN v$session s2 ON s1.sid = s2.blocking_session12WHERE s2.blocking_session IS NOT NULL13ORDER BY s2.seconds_in_wait DESC;1-- 查看锁定的具体对象2SELECT3 o.object_name,4 o.object_type,5 l.session_id,6 l.locked_mode,7 s.sql_id,8 s.username9FROM v$locked_object l10JOIN dba_objects o ON l.object_id = o.object_id11JOIN v$session s ON l.session_id = s.sid12ORDER BY o.object_name;1-- 查看正在执行的 SQL2SELECT sql_text FROM v$sql WHERE sql_id = '&blocker_sql_id';Oracle 自动解除了死锁(回滚牺牲者),但如果有长时间的锁等待阻塞了业务:
1-- Kill 阻塞者的 session2ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;34-- 例如5ALTER SYSTEM KILL SESSION '137,12345' IMMEDIATE;1# 如果 KILL SESSION 无效,使用 OS 级别 kill2# 先查找 OS 进程3SELECT spid FROM v$process4WHERE addr = (SELECT paddr FROM v$session WHERE sid = 137);56# 然后7kill -9 <spid>死锁的根本原因是多个 session 以不同顺序锁定资源。统一顺序就能消除死锁。
1-- 错误示范(两个存储过程以不同顺序更新)2-- 存储过程 A: UPDATE accounts SET ... WHERE id = 1; UPDATE accounts SET ... WHERE id = 2;3-- 存储过程 B: UPDATE accounts SET ... WHERE id = 2; UPDATE accounts SET ... WHERE id = 1;45-- 正确做法:始终按 ID 升序更新6-- 存储过程 A: UPDATE accounts SET ... WHERE id = 1; UPDATE accounts SET ... WHERE id = 2;7-- 存储过程 B: UPDATE accounts SET ... WHERE id = 1; UPDATE accounts SET ... WHERE id = 2;1-- 错误:长事务中间夹着耗时操作2BEGIN3 UPDATE orders SET status = 'processing' WHERE id = 100;4 -- 调用外部 API(可能耗时数秒)5 call_external_api();6 UPDATE orders SET status = 'completed' WHERE id = 100;7 COMMIT;8END;910-- 正确:先完成外部操作,再在事务中快速更新11BEGIN12 call_external_api(); -- 不持锁13 UPDATE orders SET status = 'completed' WHERE id = 100;14 COMMIT; -- 快速提交15END;1-- 如果行已被锁定,立即报错而不是等待2SELECT * FROM accounts WHERE id = 100 FOR UPDATE NOWAIT;34-- 或设置等待超时(秒)5SELECT * FROM accounts WHERE id = 100 FOR UPDATE WAIT 5;缺少索引会导致全表扫描时锁定过多行:
1-- 确保 WHERE 条件字段有索引2-- 否则 UPDATE ... WHERE unindexed_column = 'value' 会锁定大量行3CREATE INDEX idx_accounts_status ON accounts(status);1-- 查询历史死锁次数2SELECT name, value FROM v$sysstat WHERE name = 'enqueue deadlocks';34-- 查询近期的死锁 trace 文件5SELECT * FROM v$diag_alert_ext6WHERE message_text LIKE '%ORA-00060%'7ORDER BY originating_timestamp DESC8FETCH FIRST 10 ROWS ONLY;死锁排查是 DBA 面试高频题目。DBA 学习之路的故障排查模块(Day 81-90)覆盖了死锁、性能问题、空间不足、实例崩溃等 10 类生产故障的系统排查方法。开始学习 →