oracle坏块导致备份不了

问题:

Oracle 数据文件出现坏块(典型报错 ORA-01578 数据块损坏、ORA-19566 坏块数超过 MAXCORRUPT 限制),导致 RMAN 备份无法完成、备份任务失败,需要既处理坏块又让备份能够跑完。

方案:

场景一:先定位并确认坏块(所有处理的起点)

不要直接动手修,先把「坏块在哪个文件、哪个块、属于哪个对象、是物理坏块还是内存坏块」确认清楚。

  1. 从 alert 日志拿第一手线索 :搜索 Bad header found during backing up datafile、Corrupt block relative dba、Corrupt Block Found 等关键字,记录文件号与块号。

    sql 复制代码
    -- 查看 alert 日志(11g 及以后)
    -- adrci> show alert -tail 100
  2. 用 RMAN 校验 (不实际备份,只扫描):

    text 复制代码
    RMAN> BACKUP VALIDATE CHECK LOGICAL DATABASE;
    -- 或只校验单个数据文件
    RMAN> BACKUP VALIDATE CHECK LOGICAL DATAFILE 5;
    RMAN> VALIDATE DATAFILE 5 BLOCK 131;
  3. 查坏块登记视图 :

    sql 复制代码
    SELECT file#, block#, blocks, corruption_type, object# FROM V$DATABASE_BLOCK_CORRUPTION;
  4. 用 dbv 做文件级物理扫描 (可在库外执行):

    text 复制代码
    dbv file=/oradata/xxx/tbs_test01.dbf

    ⚠️ 注意:dbv 输出的文件编号可能不准确,不能直接把 dbv 的编号用于 BLOCKRECOVER ,需通过 VALIDATE 日志或 V$DATAFILE 核对真实文件号:

    sql 复制代码
    SELECT file#, name, status FROM V$DATAFILE;
  5. 把坏块落到对象上 (判断影响面):

    sql 复制代码
    SELECT o.owner, o.object_name, o.object_type, o.subobject_name
    FROM   dba_objects o
    WHERE  o.data_object_id = &object_id;
  6. 排除内存坏块 :若工具扫描未发现坏块、但查询仍报错,可能是缓冲区内的内存坏块,可先刷新缓冲区缓存再复测:

    sql 复制代码
    ALTER SYSTEM FLUSH BUFFER_CACHE;

场景二:按对象类型处理坏块

1)索引坏块 → 直接重建

sql 复制代码
ALTER INDEX 索引所有者.索引名 REBUILD;
-- 或指定表空间重建
ALTER INDEX 索引所有者.索引名 REBUILD TABLESPACE 目标表空间;

2)表坏块且存在可用 RMAN 备份 → 块介质恢复(Block Media Recovery,优先方案)

只恢复受损数据块,无需恢复整个数据文件,不必将数据文件或表空间离线,停机影响最小。

text 复制代码
RMAN> BLOCKRECOVER DATAFILE 5 BLOCK 131;

-- 恢复 V$DATABASE_BLOCK_CORRUPTION 中登记的全部坏块
RMAN> BLOCKRECOVER CORRUPTION LIST;

-- 限定从某时间点之前的备份恢复
RMAN> BLOCKRECOVER CORRUPTION LIST RESTORE UNTIL TIME 'SYSDATE - 7';
  • 前提条件:存在有效的全量备份 + 归档日志,且备份中对应块本身未损坏。

  • 恢复过程会输出 restoring block(s) → reading from backup piece → media recovery complete 等阶段。

  • 若损坏范围较大或块介质恢复失败,可退化为整文件恢复:

    text 复制代码
    RMAN> RESTORE DATAFILE 5;
    RMAN> RECOVER DATAFILE 5;

3)自动块介质恢复(ABMR)

Oracle 支持在查询/访问到坏块时自动触发块介质恢复;也可通过 SELECT 触发验证修复效果。修复后可再次 VALIDATE 确认 Marked Corrupt 为 0。

4)表坏块但无可用备份 → DBMS_REPAIR 标记跳过(会丢数据,谨慎评估)

适用于物理坏块无法用备份修复、且业务能接受少量数据丢失的场景。

sql 复制代码
-- 1) 建立修复表
EXEC DBMS_REPAIR.ADMIN_TABLES('REPAIR_TABLE', 1, 'USERS');
EXEC DBMS_REPAIR.ADMIN_TABLES('ORPHAN_TABLE', 2, 'USERS');

-- 2) 扫描对象,登记坏块
DECLARE
  v_num NUMBER;
BEGIN
  v_num := DBMS_REPAIR.CHECK_OBJECT(
             schema_name   => 'SCOTT',
             object_name   => 'T1',
             repair_table_name => 'REPAIR_TABLE');
END;
/

-- 3) 标记坏块
DECLARE
  v_num NUMBER;
BEGIN
  v_num := DBMS_REPAIR.FIX_CORRUPT_BLOCKS(
             schema_name => 'SCOTT',
             object_name => 'T1',
             fix_count   => NULL,
             repair_table_name => 'REPAIR_TABLE');
END;
/

-- 4) 设置跳过坏块,使对象可访问
DECLARE
  v_num NUMBER;
BEGIN
  v_num := DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(
             schema_name => 'SCOTT',
             object_name => 'T1');
END;
/
  • 边界:DBMS_REPAIR 只处理事务层/数据层的软件损坏 ,对物理损坏块的修复能力有限;标记跳过后被跳过块的数据会丢失(典型案例:1000 行的表查询后只剩 917 行,丢失 83 行)。
  • 建议:跳过只是让对象「能用」,最终应把好数据导出后重建表。

5)表坏块 → 提取好数据后重建表

通过 ROWID 分段扫描,把未损坏的数据导出到新表,再改名替换;注意可能产生重复行,需配合去重逻辑。

6)未使用的空块 → 可忽略(不影响对象访问)。

场景三:备份遇到坏块(ORA-19566),如何把备份跑完

现象:RMAN 报 ORA-19566: exceeded limit of 0 corrupt blocks,备份终止。根因是数据文件中有坏块,而 RMAN 默认 MAXCORRUPT = 0(零容忍)。

处理优先级:先尽量修复坏块,再备份;确实无法修复时才放宽容忍度。

1)首选:先做块介质恢复,再正常备份

按场景二用 BLOCKRECOVER / ABMR 修复坏块,修复后重新执行备份即可。

2)次选:临时放宽 MAXCORRUPT,让备份跳过坏块先完成

text 复制代码
RMAN> run {
  SET MAXCORRUPT FOR DATAFILE 5 TO 100;
  BACKUP DATABASE;
}
  • 含义:允许数据文件 5 在本次备份中最多忽略 100 个坏块,使备份能够完成。
  • ⚠️ 必须写在 run { } 块内 ,直接执行 SET MAXCORRUPT ... 会报 RMAN-03031: this option of set command needs to be used inside a run block。
  • 这只是「让备份先跑完」,坏块并未修复;备份完成后仍需按场景二修复坏块,并再次备份验证。

3)验证坏块是否真正消除

text 复制代码
RMAN> BACKUP VALIDATE CHECK LOGICAL DATAFILE 5;

确认输出中 Marked Corrupt = 0、各 Block Type 的 Failing Blocks 均为 0。

场景四:兜底与影响面控制

  1. 确认备份可用的前提:块介质恢复依赖有效的全量 + 归档备份;若备份链断裂,只能走 DBMS_REPAIR / 数据提取重建路线。
  2. 对象级优先 :能用备份恢复的优先 BLOCKRECOVER;索引坏块优先 REBUILD;表坏块在无备份时才考虑 DBMS_REPAIR。
  3. 数据一致性风险:DBMS_REPAIR 跳过、Extract 提取都可能造成丢行或重复行,处理前后务必核对行数与关键数据。
  4. 根因排查:坏块多由存储/IO/介质问题引起,修复后应检查存储链路,避免复发。
相关推荐
IT大白鼠1 小时前
图数据库系列 · 第 08 篇——面试收官:高频题与全景总结
数据库·面试·职场和发展·nosql·图数据库
xixiaoyunya1 小时前
定时备份数据库怎么规划周期?一套“少打扰业务、真能恢复“的策略
数据库
liangshanbo12152 小时前
主系统登录后,子系统怎么实现自动登录?
java·网络·数据库
许彰午2 小时前
05-静默安装常见报错与解决
数据库
害人终害己2 小时前
redis修改密码的地方在哪里
数据库·redis·缓存
rannn_1112 小时前
【Java面试题】高频面试题1|Java 后端、MySQL、Redis 与 RAG 面试整理
java·jvm·数据库·后端·面试
杨云龙UP2 小时前
Oracle 19c RAC到RAC Active Data Guard标准搭建与巡检指南
运维·服务器·数据库·oracle·adg·data guard·rac到rac
许彰午3 小时前
06-Oracle卸载与重装完整流程
数据库·oracle
ss2733 小时前
AI全栈实战 | 3.6-01 数据库与 ORM:学过 MyBatis 再看 SQLAlchemy,才知道“半自动“和“全自动“差在哪
数据库·mybatis