查RAC全局死锁必须看GES trace而非仅alert.log,因真正决定跨实例循环等待与牺牲会话的逻辑全在GES层,关键日志为lmd0_*.trc,核心视图为gv$ges_blocking_enqueue,可定位阻塞源头节点及资源争用详情。
查 RAC 全局死锁必须看 GES trace,不是只盯 alert.log
ora-00060 在 rac 环境下不能只当单实例处理——alert.log 里只记“检测到死锁”,但真正决定谁被牺牲、为什么跨实例形成循环等待的,全在 ges(global enqueue service)层的日志里。rac 死锁默认检测间隔是 60 秒(由 _lm_dd_interval 控制),这期间多个实例的锁请求已在 ges 中堆积,仅靠 v$lock 或 v$session 查到的只是“结果”,不是“路径”。
关键动作:
- 先定位 GES trace 文件:在
Diag Trace目录下找形如inst1_lm_*.trc或inst2_lm_*.trc的文件(lm= lock manager) - 用
grep -A 10 -B 5 "DEADLOCK" inst1_lm_*.trc提取包含死锁上下文的段落,重点看*** GES DEADLOCK DETECTED ***块 - 注意每个会话的
INST_ID和GRANT_LEVEL(如X表示排他,S表示共享),跨实例的 X→S 或 S→X 升级冲突是高频诱因
用 gv$ges_blocking_enqueue 定位跨实例阻塞链
单查 v$lock 在 RAC 下会漏掉 GES 层的 enqueue 状态,必须用全局视图 gv$ges_blocking_enqueue。这个视图能暴露哪个实例上的哪个资源(比如 TX-000A0001-00000F4C)正被哪个会话持有、又被哪个远程实例的会话请求。
典型查询:
SELECT inst_id, event, state, blocking_inst_id,
resource_name1, resource_name2,
sid, serial#
FROM gv$ges_blocking_enqueue
WHERE state = 'BLOCKING' OR state = 'WAITING';
常见陷阱:
-
resource_name1是锁类型+对象 ID(如TX-000A0001-00000F4C),不是表名,需结合dba_objects反查:SELECT object_name FROM dba_objects WHERE data_object_id = TO_NUMBER('00000F4C','XXXXXXXX') - 如果
blocking_inst_id和当前inst_id不同,说明阻塞来自另一个节点——这是单实例脚本查不到的 -
event字段值为enq: TX - row lock contention是表象,真实根因常藏在resource_name2(如事务号、回滚段号)里
kill session 不生效?先确认是不是 LMD 进程卡住
RAC 中执行 ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE 后仍卡死,大概率不是会话没杀掉,而是 LMD(Lock Manager Daemon)进程本身陷入 hang 或高负载,无法及时广播 kill 指令到其他实例。
验证步骤:
- 查 LMD 进程状态:
ps -ef | grep lmd,观察 CPU 占用是否持续 >90%,或有lmd进程处于D(uninterruptible sleep)状态 - 检查 LMD trace:
tail -n 100 inst1_lmd_*.trc,搜索"LMD: Deadlock detection started"和后续超时标记,若长时间无后续日志,说明检测流程卡在 GES 内部 - 紧急绕过方式:在操作系统层直接
kill -9对应的 shadow process(从v$process.spid查),但仅限业务完全不可用时——这会强制断开连接,可能丢事务
避免 RAC 死锁不能只改 SQL,得控锁粒度和事务边界
单实例优化那套“按主键排序 update”在 RAC 下效果打折——因为行锁升级为 ITL 争用或跨块索引分裂后,GES 要协调的不只是行,还有数据块头、索引分支节点等资源。
实操要点:
- 对高频并发更新的表,显式设置
INITRANS≥ 16,避免 ITL 争用触发额外 GES 请求 - 禁用
ENABLE ROW MOVEMENT(除非真需要),否则分区表更新可能引发跨块迁移,触发 GES 全局重定位 - 存储过程中避免
SELECT ... FOR UPDATE后隔太久才UPDATE,RAC 下这种“长持锁+短操作”极易被其他实例的相同语句命中同一块 - 应用层加分布式锁(如 Redis)比依赖 Oracle 锁更可控——尤其当业务逻辑天然要求“先查再判再改”时
最易被忽略的一点:RAC 死锁报告里出现大量 US(Undo Segment)类资源等待,往往意味着 undo 表空间不足或 undo_retention 设置过低,导致事务回滚段被复用,GES 不得不频繁协调旧事务的 undo 链。这不是锁设计问题,是容量配置缺陷。











