ORA-00600是数据库内核未预期状态触发的内部错误,需提取完整参数、分析trace文件堆栈/内存/SCN段,并结合v$session与v$sql定位真实SQL及绑定值;而ORA-00060是死锁检测引发的业务级并发异常,含明确“Deadlock detected”提示和Deadlock graph,二者本质不同,混淆将导致诊断方向错误。
ora-00600 不是死锁错误,它和 ora-00060 完全无关。混淆这两者会导致诊断方向彻底错误——你花一小时查 ora-00600 的 trace 文件,实际问题却是 ora-00060 死锁,而真正该看的 deadlock graph 一直被忽略。
ORA-00600 和 ORA-00060 的本质区别
ORA-00060 是 Oracle 主动检测到死锁后,选择一个 victim 事务并回滚它时抛出的**业务级并发异常**,日志里明确写“Deadlock detected”,trace 文件中必含 Deadlock graph 段落。
ORA-00600 是数据库内核遇到未预期状态时触发的**内部错误**,参数(如 [kghstack_free2]、[-4012])才是关键线索,与死锁逻辑无关。它可能由 bug、内存损坏、参数非法、SQL 解析异常等引发。
- 查 alert log 时,
ORA-00060后通常紧跟着 “ORA-06512at line X” 和堆栈;ORA-00600后则带一串方括号参数和 call stack 地址 -
ORA-00060可安全重试(配合延迟+次数限制);ORA-00600不能盲目重试,需先归档 trace 并分析参数含义 - PL/SQL 中捕获
ORA-00060用WHEN OTHERS THEN IF SQLCODE = -60;捕获ORA-00600必须靠WHEN OTHERS+IF SQLCODE = -600,但极少这么做——因为它代表底层异常,不应由业务逻辑吞掉
存储过程中无法“捕获并分析”ORA-00600堆栈
Oracle 不允许在 PL/SQL 运行时动态读取或解析当前会话的 trace 文件内容。所谓“在存储过程中分析堆栈”,实际是误传——你只能让 Oracle 自动生成 trace,然后人工或脚本去文件系统提取。
-
ORA-00600触发时,Oracle 自动在diagnostic_dest下生成 trace 文件,命名含_ora_<pid>.trc</pid>,路径可通过SELECT value FROM v$diag_info WHERE name = 'Default Trace File';查得 - 存储过程里调用
DBMS_SUPPORT.START_TRACE或DBMS_MONITOR是为**主动开启**跟踪,不是为捕获已发生的ORA-00600 - 试图在
EXCEPTION块里用UTL_FILE读取刚生成的 trace 文件,大概率失败:文件可能尚未 flush、权限不足、或已被归档压缩
真正该做的:定位 + 归档 + 查官方文档
遇到 ORA-00600,重点不是写代码去“分析”,而是快速锁定原始上下文,并交给 DBA 或 Oracle Support。
- 立即执行:
SELECT * FROM v$diag_info;找到Diag Trace路径,再用 OS 命令(如ls -lt *.trc | head -5)找最新 trace 文件 - 从 alert log 复制完整错误行,例如:
ORA-00600: internal error code, arguments: [kkslpdt: timeout], [0x000000000], [], [], [], [], [], []—— 方括号里的第一个字符串就是关键 ID - 用这个 ID 去 My Oracle Support(MOS)搜 Note,比如搜索
kkslpdt: timeout,通常能匹配到已知 bug、补丁号(如 Patch 32198765)和临时规避方案 - 若参数是数字型(如
[-4012]),查 MOS 文档ORA-600/ORA-7445/ORA-700 Error Look-up Tool,输入参数值获取解释
为什么你看到的“捕获堆栈”示例都是错的
网上不少“用 DBMS_UTILITY.FORMAT_ERROR_BACKTRACE 获取 ORA-00600 堆栈”的代码,本质是混淆了错误层级:
-
FORMAT_ERROR_BACKTRACE只能返回 PL/SQL 执行路径(即你写的存储过程哪一行出的错),对ORA-00600这种内核级崩溃毫无意义 -
ORA-00600的真实堆栈藏在 OS 层 trace 文件里,包含 C 函数调用链(如kgeasnmierr → kgerinv → kkslpdt),PL/SQL 无法访问 - 强行在 EXCEPTION 块里记录
SQLERRM,得到的只是 “ORA-00600: internal error code...” 字符串,丢失全部参数细节和 call stack
真正需要警惕的是:把 ORA-00600 当作普通异常去 catch、log、retry,既掩盖了严重性,又错过第一时间收集诊断信息的窗口。它的出现,意味着数据库某处已脱离可控状态——这不是代码能修的,是必须停机评估或打补丁的信号。


















