不能直接继续——DBMS_REPAIR.CHECK_OBJECT遇坏块立即报ORA-01578并中止,仅输出坏块位置且不修改数据;需先用FIX_CORRUPT_BLOCKS标记、再用SKIP_CORRUPT_BLOCKS设置跳过模式,并启用EVENT 10231及刷新缓存才能使查询跳过坏块。
DBMS_REPAIR.CHECK_OBJECT 报 ORA-01578 错误时还能继续吗
不能直接继续——dbms_repair.check_object 遇到坏块会立即报 ora-01578: oracle data block corrupted 并中止,它本身不提供“跳过”选项。这个函数只做诊断,不是数据抢救工具。
真正能绕过坏块读数据的,是后续的修复+跳过组合动作。关键在两步:先用 DBMS_REPAIR 标记坏块为“corrupt”,再让查询避开这些块。
-
DBMS_REPAIR.CHECK_OBJECT只输出坏块位置(file_id/block_id),不修改任何东西 - 必须紧接着调用
DBMS_REPAIR.FIX_CORRUPT_BLOCKS,把坏块加入 corruption list - 之后启用
EVENT 10231或设置DB_BLOCK_CHECKING=OFF(仅限诊断期,不可长期开启)才能让全表扫描跳过它们
如何让 SELECT * FROM 表名 跳过已标记的坏块
Oracle 默认不会跳过坏块,即使你已用 DBMS_REPAIR 标记过。要生效,必须配合隐式事件或参数调整,且仅对某些访问路径有效。
最常用、副作用相对可控的方式是会话级启用 EVENT 10231:
ALTER SESSION SET EVENTS '10231 trace name context forever, level 10';
然后执行查询。注意:
- 该事件只对
FULL TABLE SCAN和INDEX FAST FULL SCAN生效,走索引范围扫描或唯一键查找仍会报错 - 返回结果里**不会包含坏块所在行**,也不会报错,但你要意识到这部分数据永久丢失了
- 10231 在 Oracle 12c 及以后版本仍可用,但官方文档已不提——它属于“未废弃但不承诺支持”的隐式事件
DBMS_REPAIR.FIX_CORRUPT_BLOCKS 执行后为什么查询还是报错
常见原因是没刷新 buffer cache 或没重连会话。标记坏块只是写入数据字典(SYS.REPAIR_TABLE),Oracle 的读取路径不会自动感知。
必须确认以下三点都完成:
- 执行过
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(不是FIX_...)将目标表设为跳过模式:BEGIN DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('SCHEMA_NAME', 'TABLE_NAME'); END; - 当前会话已启用
EVENT 10231(如上) - 执行
ALTER SYSTEM FLUSH BUFFER_CACHE或断开重连,确保新会话不缓存旧的块状态
漏掉任意一步,查询仍会卡在坏块上,报 ORA-01578 或 ORA-01110。
跳过坏块后导出数据,哪些方式实际可行
CTAS(CREATE TABLE AS SELECT)和 EXPDP 是唯二较稳妥的选择;SQL*Plus SPOOL 或应用直连查出来再拼 INSERT,大概率在坏块位置中断。
推荐顺序:
- 先用
EVENT 10231+SKIP_CORRUPT_BLOCKS确保SELECT COUNT(*)不报错,再跑 CTAS - CTAS 语句里加
NOLOGGING加速,但注意归档日志无法恢复这部分新表 -
EXPDP需配合FLASHBACK_TIME或QUERY参数分批导,避免单次扫描跨太多坏块;纯TABLES=xxx仍可能失败
坏块位置越靠近表头部(比如 segment header 坏了),能抢救的数据越少——这时候别硬扛,优先从备份恢复更省时间。










