这是一篇真实处理过程的记录环境为 Oracle 11.2.0.4、做过switchover适用版本范围11.1 之后、12.2 之前已确认受影响版本包括 11.1.0.7、11.2.0.2、11.2.0.3、11.2.0.4、12.1.0.1、12.1.0.2。相关 Bug22241601Doc ID 1608167.1。关键词ORA-00600 [ktbdchk1: bad dscn]、查询耗时 0 秒即返回 ORA-01555、Wrong Results、Data Guard、Switchover / Failover、索引块 ITL、_ktb_debug_flags、DBV check code 6056。问题是怎么暴露的阶段一业务报 ORA-00600 [ktbdchk1: bad dscn]客户反馈某个业务模块执行 INSERT 时报错ORA-00600: 内部错误代码, 参数: [ktbdchk1: bad dscn], [], [], [], [], [], [], [], [], [], [], []第一反应是查 trace。trace 中的自定义 dump 部分给出了非常明确的信息[ktbdchk] -- ktbgcl4 -- bad dscn dependent scn: 0x003e.d191d5cd recent scn: 0x003e.34fa6996 current scn: 0x003e.34fa6996依赖 SCN 比当前 SCN 大了 55这在逻辑上不可能合法存在。调用栈也指向了索引插入路径ktbValidateDependentScn() - ktbgcl1() - ktbgfi() - kdiins0() - kdiinsp() - kauxsin() - qesltcLoadIndexList()判断问题出在索引块的 ITL 提交 SCN。当时客户对相关索引执行了ALTER INDEX ... REBUILD ONLINE业务恢复。阶段二查官方文档确认 Bug 22241601带着 trace 里的ktbdchk1: bad dscn去查 Oracle 文档命中Bug 22241601Doc ID 1608167.1。该 Bug 的标题是ORA-600 [kdgsgrp1] / ORA-1555 / ORA-600 [ktbdchk1: bad dscn] / ORA-600 [2663] ktbdGetDependentScndue to Invalid Commit SCN in INDEX block对照 trace 中的dependent scn current scn以及调用栈指向kdiins0()/kdiinsp()现象与该 Bug 完全一致。确认索引块 ITL 中写入了无效的提交 SCN这不是物理块损坏索引列数据本身是完好的损坏的是 ITL 元数据。阶段三之后又遇到查询耗时 0 秒的 ORA-01555过了一段时间另一条 SELECT 查询出现了非常反直觉的报错ORA-01555 caused by SQL statement below (SQL ID: dk20y0kwcffuq, Query Duration0 sec, SCN: 0x003e.3afa0992)第一反应和大多数人一样查 undo 表空间、undo_retention、是否有大事务撑爆 undo。结论是undo 完全充足执行查询立马报错传统 ORA-01555 的解释在这里不成立。但结合已经确认的 Bug 22241601这个现象其实并不意外。该 Bug 的官方说明中明确列出 ORA-1555 是它的典型表现之一。查询使用受影响的索引做一致性读时由于索引块 ITL 中的提交 SCN 非法Oracle 无法为该块建立合法的读一致性视图于是将这种 SCN 层面的不一致上报为 ORA-01555即使查询耗时接近 0 秒。对这条 SQL 实际使用的索引执行重建后业务恢复。两次都是“重建索引有效”但报错形式不同一次是 INSERT 路径撞上坏索引块触发 ORA-00600一次是 SELECT 路径撞上坏索引块触发 ORA-01555。根因索引块 ITL 中的无效提交 SCNOracle 访问数据块时会检查依赖 SCN 是否合法正常要求依赖 SCN 当前数据库 SCN该 Bug 的根因是索引块的 ITL 槽位中记录了无效的提交 SCN导致依赖 SCN 大于当前 SCN触发内部一致性检查失败。这里需要强调一个容易误解的点索引块中的数据列值没有损坏损坏的只是 ITL 中的提交 SCN 元数据。因此重建索引可以修复因为重建会生成全新的、SCN 合法的索引块。这也解释了为什么同一根因可以表现为多种不同的前台错误INSERT 在索引维护阶段触发ORA-00600 [ktbdchk1: bad dscn]SELECT 在一致性读阶段触发ORA-01555包括 Query Duration 0 秒的情况在某些场景下还可能触发ORA-600 [kdgsgrp1]、ORA-600 [2663]出现Wrong Results使用受影响索引的查询静默返回不完整结果集。三、触发前提不能只看“有没有做过切换”Data Guard 环境执行 Switchover / Failover 之后是最高频的触发场景主库和备库都可能中招版本落在 11.1 之后、12.2 之前且索引块 ITL 中出现了无效的提交 SCN。Switchover / Failover 是最常见诱因但不能因为“没做过切换”就排除这个 Bug。四、三种处理方式及实际效果方式 1设置_ktb_debug_flags8在没有打补丁的环境中可以通过设置隐含参数来规避ALTER SYSTEM SET _ktb_debug_flags 8 SCOPE BOTH;这个参数是动态的可以在线设置不需要重启实例。设置后Oracle 在 index block cleanout 时会对已存在的无效 ITL SCN 进行自愈并在 alert log 中留下类似Healing Corrupt DLC ITL的提示。对于 Data Guard 环境需要在主库和备库两侧都设置。需要注意这个参数是临时规避手段。它适合作为补丁前的过渡方案不适合作为长期方案。方式 2主备库打补丁 22241601这是最终的修复方式。补丁 22241601 在 Data Guard 环境中的安装有特殊要求不能滚动安装。官方要求的顺序是关闭主库SHUTDOWN NORMAL或IMMEDIATE确认所有备库已应用主库产生的 redo关闭备库在备库安装补丁启动到 mount 或 open read only重启备库的 managed recovery在主库安装补丁打开 read/write。关于_ktb_debug_flags与补丁的关系这里需要说清楚打完补丁 22241601 之后不需要再手工设置_ktb_debug_flags8因为补丁会自动将该隐含参数设置为 8。打补丁后的参数值补丁安装后自愈成为默认行为之前手工设置的_ktb_debug_flags8可以移除。补丁防止新的无效 ITL SCN 被引入的能力不依赖任何参数参数值只影响是否对已经存在的坏块尝试自愈。补丁的作用可以概括为防止新问题从根本上阻止无效 ITL SCN 被写入索引块尝试修复旧问题默认开启自愈尝试修复磁盘上已存在的无效 ITL SCN但不保证 100% 修复所有已有坏块。官方明确说明“may not repair all existent cases”。如果补丁的自愈没有覆盖到某个块仍然需要手动重建索引若问题触发在备库则对主库进行操作利用同步恢复备库。方式 3用 DBV 检查谨慎在生产环境使用建议是对环境进行克隆后执行适用于11.2的版本若是Versions 9.2 but BELOW 11.2需要先打补丁 KI5104否则可能只报通用块损坏看不到明确的 6056 和 ITL SCN 信息。DBVDBVERIFY可以定位这类 ITL SCN 异常。在 DBV 日志中典型标志是itl[itl_id] has higher commit scn(aaa.bbb) than block scn (xx.yy) Page Block failed with check code 6056check code 6056是该问题的特征码。DBV 的输出可以直接看到“ITL 的提交 SCN 高于块的 SCN”使用方式dbv file/u01/app/oracle/oradata/orcl/datafile/anew.366.1219507701如果已经通过 trace 或dba_extents定位到了具体索引也可以用SEGMENT_ID做更精确的检查。方式 4 利用执行查询报错ORA-1555的特性强制SQL走索引依次执行select 操作进行排查索引问题SELECT SELECT /* INDEX(a ||ind.index_name||) */ COUNT(t.||co.column_name||) FROM ||ind.owner||.||ind.table_name|| a;||chr(10) ,ob.last_ddl_time FROM dba_indexes ind join dba_objects ob on ind.index_nameob.object_name join dba_ind_columns co on co.index_name ind.index_name WHERE index_type NOT IN (BITMAP,LOB,IOT - TOP) AND ind.owner TEST and co.column_position1 AND ind.owner NOT IN (SYS,SYSTEM,XDB,OUTLN,APPQOSSYS,DBSNMP,WMSYS) AND ind.statusVALID and ob.last_ddl_time to_timestamp(2026/10/8 12:10:27,yyyy/mm/dd hh24:mi:ss) ORDER BY ob.last_ddl_time desc ,ind.owner,ind.index_name;五、为什么两次都是“重建索引有效”重建索引之所以能恢复业务原因并不复杂重建会丢弃旧的索引块生成全新的、SCN 状态合法的索引块。原来那些带有无效 ITL 提交 SCN 的块不再被业务路径访问问题自然消失。但这也带来一个需要注意的点如果同一张表上有多个索引而只重建了报错路径上碰到的那个其他索引上的无效 SCN 仍然存在。它们可能在后续以另一种形式暴露这次是 INSERT 路径的 ORA-00600下次可能是 SELECT 路径的 ORA-01555。因此在排查时应当尽量确认所有相关索引的状态而不是只重建第一个报错时触发的索引。