必须先确认坏块真实存在,再执行BLOCKRECOVER;查V$DATABASE_BLOCK_CORRUPTION仅反映未修复的逻辑坏块(重启清空),为空不代表无坏块,需运行VALIDATE DATABASE CHECK LOGICAL或VALIDATE DATAFILE n主动扫描,物理坏块则需DBV或dd验证。

怎么确认坏块真实存在,不是误报
直接跑 BLOCKRECOVER 很可能白忙一场——RMAN 不会自己“猜”哪块坏了。它只响应已知线索,比如 V$DATABASE_BLOCK_CORRUPTION 里有记录,或你主动用 VALIDATE 扫出来。
这个视图只存“最近一次检测到但还没修”的逻辑坏块,实例重启就清空,不能当实时监控用。
- 先查:
SELECT * FROM V$DATABASE_BLOCK_CORRUPTION;,为空不代表没坏块 - 再主动扫:
VALIDATE DATABASE CHECK LOGICAL;或更精准的VALIDATE DATAFILE 4;,它真读盘、校验块头和 ITL,比备份扫描靠谱 - 如果是 NOLOGGING 操作引发的坏块(常见于备库),12c+ 要用:
VALIDATE DATABASE NONLOGGED BLOCK;,查V$NONLOGGED_BLOCK而不是V$DATABASE_BLOCK_CORRUPTION
物理坏块(如磁盘扇区损坏)可能绕过 Oracle 校验,这时得靠存储日志,或用 dd if=/dev/xxx bs=8192 count=1 skip=N 手动读块验证。
BLOCKRECOVER 命令必须带哪些参数才不失败
BLOCKRECOVER 不是智能命令,漏一个关键参数就卡住或报错,比如 ORA-19625(找不到文件)或 RMAN-06053(缺归档日志)。
- 必须显式写:
BLOCKRECOVER DATAFILE 5 BLOCK 12345;—— 文件号和块号一个都不能少,不能只写表名或对象名 - 多个块用逗号分隔:
BLOCKRECOVER DATAFILE 5 BLOCK 12345,12346,12347;,不支持12345-12347这种范围写法 - 想指定备份集恢复?加:
FROM BACKUPSET 'xxx',但该备份集必须含该数据文件的完整映像(增量备份不行) - 不加
FINISH RECOVERY,RMAN 只做块还原 + 前滚,不会 open 数据库;后续还得手动RECOVER DATAFILE 5补归档日志
为什么 BLOCKRECOVER 后还是报 ORA-01578
修复失败不一定是命令写错了,更多是依赖条件没满足。RMAN 的本质是“拿备份里的干净块覆盖当前坏块”,一旦源头或路径断了,就无解。
- 备份本身也含坏块?查:
LIST BACKUP OF DATAFILE 5;看最近备份时间,再VALIDATE BACKUPSET <handle></handle>确认能读出对应块 - 报
RMAN-06053: unable to perform media recovery because of missing log?说明归档日志缺失,BLOCKRECOVER 需日志把块前滚到当前 SCN - 坏块在 undo 或临时表空间?
BLOCKRECOVER无效——这些块不参与一致性校验,直接重建数据文件更稳妥 - 索引块损坏?优先试:
ALTER INDEX idx_name REBUILD ONLINE;,比反复修块更高效
修复后必须立刻做的两件事
执行完 BLOCKRECOVER 不代表结束。Oracle 只把块还原并前滚,但没强制刷新缓存、也没验证是否真好了。
- 立刻做一次
CHECKPOINT;,确保所有脏块刷盘,避免后续读取仍命中旧缓存 - 马上再跑一遍
VALIDATE DATAFILE 5;,确认坏块已消失;如果V$DATABASE_BLOCK_CORRUPTION还有记录,说明没修干净或又出了新坏块
文件头(block 1)损坏是 RMAN 的盲区——它无法修改第 1 号块,遇到 ORA-01122 或 ORA-01210 必须放弃 RMAN,改用 BBED 或从备份提取干净文件头手工修复。


















