ora-19566是数据库主动拒绝带病备份的完整性保护机制,非操作失败;须先查v$database_block_corruption定位坏块,再通过dba_extents映射对象、dbv验证,最后用blockrecover修复或重建索引,而非盲目设maxcorrupt。

ORA-19566 不是备份失败,而是数据库在说:“我发现了坏块,但你没告诉我能不能跳过它。” 直接设 set maxcorrupt 可能让备份跑完,但恢复时照样报 ORA-01578——那块数据还是坏的。
先查清楚坏块在哪、影响什么对象
别急着改参数。RMAN 报这个错,说明 v$database_block_corruption 里已经有记录,或者当前扫描时实时发现了损坏。必须先定位:
- 运行
SELECT * FROM v$database_block_corruption;,拿到FILE#、BLOCK#、CORRUPTION_TYPE - 用
DBA_EXTENTS反查对象:SELECT segment_name, segment_type, owner FROM dba_extents WHERE file_id = &F AND &B BETWEEN block_id AND block_id + blocks - 1;(把&F和&B换成上一步的值) - 对疑似数据文件补一刀验证:
dbv file=/path/to/datafile.dbf blocksize=8192,看是否输出Fractured block或校验失败
这三步漏掉任何一环,后续操作就等于蒙眼修车。
set maxcorrupt 只能在 run 块里对指定 datafile 生效
maxcorrupt 是 session 级、命令级、目标绑定的临时开关,不是全局配置,也不持久化。常见错误写法包括:
-
set maxcorrupt to 10—— 语法非法,必须带for datafile N - 在
run { }外执行set maxcorrupt—— 完全不生效 - 只设一次却有多个坏块分布在不同文件(如
FILE#显示 3、7、12 都有)—— 必须为每个文件单独设
正确写法示例:
run {
set maxcorrupt for datafile 4 to 5;
set maxcorrupt for datafile 7 to 3;
backup datafile 4, 7;
}
注意:设成 100 不代表“安全”,只代表你允许 RMAN 把最多 100 个坏块原样复制进备份集——这些块在 restore 时仍会出问题。
修复比跳过更重要,BLOCKRECOVER 有硬性前提
BLOCKRECOVER 只修物理坏块,且依赖两个东西:可用的完整备份 + 覆盖该块修改时间点的归档日志。漏一个就失败:
-
BLOCKRECOVER DATAFILE 4 BLOCK 123;—— 必须同时指定文件号和块号,不能只写表名 - 批量修复只能列明具体块号:
BLOCKRECOVER DATAFILE 4 BLOCK 123,124,125;,不支持123-125这种范围写法 - 如果报
ORA-19625(无法识别文件),先查v$datafile确认路径是否被重命名过;若报no backup of block found,说明该块在上次备份时就已经坏了,得找更早备份
修复后必须手动清理 buffer cache 并验证:ALTER SYSTEM FLUSH BUFFER_CACHE;,再跑一次 VALIDATE DATAFILE 4; 确认视图清空、块可读。
逻辑坏块优先重建索引,表坏块慎用 10231 事件
如果是索引结构错乱这类逻辑坏块,成本最低的方式就是重建:DROP INDEX idx_name; CREATE INDEX idx_name ON ...;。表级坏块才考虑绕过:
-
ALTER SYSTEM SET EVENTS '10231 trace name context forever, level 10';—— 注意:19c 多租户下该事件可能失效 - 用
CREATE TABLE tab_tmp AS SELECT * FROM bad_table;拷贝未损坏行 - 重命名原表、交换表名、重建索引/约束/trigger
整个过程不会修复坏块本身,只是把还能读的数据抢救出来。真正缺失的数据,得靠业务逻辑补全——这点最容易被忽略。











