首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Every Day of a DBA,第154期: Oracle 19c Active Data Guard — Automatic Block Media Recovery (ABMR)

Every Day of a DBA,第154期: Oracle 19c Active Data Guard — Automatic Block Media Recovery (ABMR)

作者头像
用户3107127
发布2026-07-21 14:20:32
发布2026-07-21 14:20:32
120
举报

1. 文档目的

ABMR 仅修复物理坏块(Physical Block Corruption),绝不修复逻辑坏块(Logical Block Corruption)。

本文档涵盖:

  • ABMR 工作原理与架构
  • 生效的硬性前提条件(四条件缺一不可)
  • 物理坏块 vs 逻辑坏块的本质区别
  • ABMR 触发验证方法(而非"凭感觉以为在工作")
  • 逻辑坏块在备库上的正确修复路径
  • 常见误区和故障排除

2. Automatic Block Media Recovery (ABMR)

ABMR 是 Oracle Active Data Guard 提供的一项自动块级故障恢复机制。当主库或备库在运行时遇到 物理坏块(物理 I/O 读取失败,块校验和不匹配),ABMR 会自动从另一端的数据库(备库或主库)获取该块的完好副本,透明地覆盖损坏块,无需人工干预。

核心工作流程

代码语言:javascript
复制
┌─────────────────────────────────────────┐
│     客户端查询触发物理块 I/O 失败          │
│     ORA-01578: 文件 X 块 Y 读取失败       │
└─────────────────┬───────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│   Oracle 内核检测到校验和错误或块格式错误   │
│   校验: 块是否属于可自动修复的物理坏块       │
│   ✗ 逻辑坏块 → 不触发 ABMR,直接报错       │
│   ✓ 物理坏块 → 进入 ABMR 流程             │
└─────────────────┬───────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│  ABMR 通过网络从另一端数据库请求块的副本     │
│                                          │
│   备库出错 → 从主库 FETCH 干净块            │
│   主库出错 → 从备库 FETCH 干净块            │
└─────────────────┬───────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│  接收到块副本后, 写入损坏位置, 刷新缓存      │
│  记录日志:                                  │
│  "Automatic block media recovery:          │
│   successfully restored block Y from       │
│   <source>"                                │
└─────────────────────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│  客户端重新尝试读取 — 成功                  │
│  整个流程对应用完全透明                      │
└─────────────────────────────────────────┘

3. ABMR 生效的四个硬性前提条件

以下条件 必须同时满足,缺一不可。任何一个不满足,ABMR 都不会触发,且不会报明显错误(仅告警日志中记录静默跳过)。

条件 1:备库 OPEN_MODE 必须为 READ ONLY WITH APPLY

代码语言:javascript
复制
SELECT OPEN_MODE, DATABASE_ROLE FROM V$DATABASE;

正确值

错误值

READ ONLY WITH APPLY

READ ONLY(无 Real-Time Apply)

MOUNTED(备库未打开)

READ WRITE(这在备库不可能)

⚠️ 常犯错误:仅设置了 READ ONLY 而没有 WITH APPLY,MRP 进程不运行,ABMR 初始化直接失败。

条件 2:MRP0 进程必须处于 APPLYING_LOG 状态

代码语言:javascript
复制
SELECT PROCESS,STATUS, CLIENT_PID, THREAD#, SEQUENCE#
FROM V$MANAGED_STANDBY
WHERE PROCESS LIKE'MRP%';

正确状态

错误状态

APPLYING_LOG

IDLE(Redo 应用暂停)

WAITING_FOR_LOG(无可用归档)

进程不存在(MRP 未启动)

条件 3:Active Data Guard 许可必须为 TRUE

代码语言:javascript
复制
SELECT*FROM V$OPTION WHERE PARAMETER ='Active Data Guard';

正确值

错误值

TRUE

FALSE(无 ADG 许可,ABMR 永远不工作)

这是 最容易被忽略的硬性条件。即使备库在运行,很多站点仅使用了 Oracle Data Guard(免费许可)而非 Active Data Guard(需要额外购买许可),ABMR 功能在内核层被禁用。

条件 4:LOG_ARCHIVE_CONFIG 必须在主备两端都包含完整的 DG 名称

代码语言:javascript
复制
-- 主库检查
SHOW PARAMETER log_archive_config;

-- 备库检查
SHOW PARAMETER log_archive_config;

正确示例:

代码语言:javascript
复制
log_archive_config = 'DG_CONFIG=(orcl,orcl_stby)'
--                      ↑ 主库 DB_UNIQUE_NAME  ↑ 备库 DB_UNIQUE_NAME

错误示例:

代码语言:javascript
复制
log_archive_config = 'DG_CONFIG=(orcl)'            -- 漏了备库名称
log_archive_config = 'DG_CONFIG=(orcl_stby)'       -- 漏了主库名称
log_archive_config = ''                             -- 空值

如果主备任意一端漏掉了对方的 DB_UNIQUE_NAME,ABMR 的跨库块级拉取通道在初始化时就会失败。


4. 物理坏块 vs 逻辑坏块 — 本质区别

这是 ABMR 主题下 最核心、最容易被误解 的概念。

4.1 物理坏块(Physical Corruption)

特征

说明

定义

块在存储介质层面已损坏(磁盘扇区损坏、RAID 校验失败、存储缓存故障)

检测方式

Oracle 读取块后,计算校验和与块头中记录的校验和不匹配

表现

ORA-01578: ORACLE data block corrupted (file # X, block # Y)

V$DATABASE_BLOCK_CORRUPTION

CORRUPTION_TYPE = 'FRACTURED' 或 'CHECKSUM'

根源

存储层问题,数据库内部结构本身无问题

ABMR 是否工作

✅ 是 — 从另一端拷贝完好副本即可修复

4.2 逻辑坏块(Logical Corruption)

特征

说明

定义

块校验和与头格式都正确,但块内部数据逻辑结构已损坏(如索引条目指向不存在的数据行、事务槽(ITL)损坏、行目录溢出)

检测方式

ANALYZE TABLE ... VALIDATE STRUCTURE CASCADE、RMAN VALIDATE CHECK LOGICAL、DBVERIFY 加 logonly=yes 参数

表现

ORA-01498: block check failure、查询返回不一致数据、索引查询报错

V$DATABASE_BLOCK_CORRUPTION

CORRUPTION_TYPE = 'LOGICAL' 或 'MEDIUM'

根源

Oracle 内部逻辑损坏(Bug、异常关闭、介质恢复时 Redo 损坏、人为操作)

ABMR 是否工作

❌ 否 — 备库上的同一块也可能逻辑损坏(如果损坏来自 Redo 重放)

4.3 对比总结

比较维度

物理坏块

逻辑坏块

校验和

❌ 不匹配

✅ 匹配

块头格式

❌ 错误或不可读

✅ 正确

内部数据逻辑

未知

❌ 不一致/损坏

ABMR 能否修复

✅ 能

❌ 不能

需要 RMAN 备份

不需要(利用对端副本)

需要

典型根因

磁盘坏道、RAID 故障、SSD 异常

Oracle Bug、异常关闭、Redo 损坏


5. 逻辑坏块为什么无法触发 ABMR — 深入解析

5.1 根因:逻辑损坏可能在备库上同样存在

ABMR 的核心假设是:另一端数据库的同一数据块是完好的

  • 主库物理坏块 → 备库完好 ✅ 成立(备库通过 Redo 重放获得了正确副本)
  • 备库物理坏块 → 主库完好 ✅ 成立(主库是原始数据来源)
  • 备库逻辑坏块 → 主库可能也坏 ❌ 不成立

为什么?因为逻辑坏块的成因可能是:

  1. Redo 日志损坏:主库写入坏 Redo,传到备库重放后,备库也产生同样的逻辑损坏
  2. Oracle Bug 触发的逻辑损坏:主库某版本 Bug 导致段内逻辑结构损坏,Redo 记录的是损坏后的状态,备库重放后也损坏
  3. 备库自身异常:备库文件系统异常、存储缓存损坏,导致 Redo 应用到备库后产生逻辑损坏(但主库完好)

在上述场景 #1 和 #2 中,即使 ABMR 从主库拉取块副本,拿到的也是 同样损坏的逻辑块,修复无意义。

5.2 ABMR 的防御机制

Oracle 内核在决定是否触发 ABMR 时,会判断坏块的类型:

  • 如果块校验和错误 → 物理坏块 → 发起 ABMR
  • 如果块校验和正确但逻辑检查失败 → 逻辑坏块 → 跳过 ABMR,直接报错返回给客户端
代码语言:javascript
复制
-- 通过告警日志验证 ABMR 是否尝试触发
-- 逻辑坏块:仅看到 ORA-01578,无 ABMR 相关日志
-- 物理坏块:ORA-01578 后紧跟 "Automatic block media recovery: requesting block..."

6. 验证 ABMR 是否真正在工作(而不是你以为它在工作)

6.1 通过告警日志验证

这是 最硬、最可靠 的验证方法。不要只看参数设置,要实际模拟故障并观察日志。

代码语言:javascript
复制
-- 查看主库告警日志路径
SELECTVALUEFROM V$DIAG_INFO WHERE NAME ='Diag Alert';
代码语言:javascript
复制
# tail 实时跟踪
tail -f$ORACLE_BASE/diag/rdbms/<db_name>/trace/alert_<sid>.log | grep-i"automatic block media recovery"

看到以下输出 = ABMR 真正在工作:

代码语言:javascript
复制
Automatic block media recovery: requesting block 1234 from standby for file 5
Automatic block media recovery: successfully restored block 1234 from standby for file 5

只看到以下内容 = ABMR 没有触发(逻辑坏块或条件不满足):

代码语言:javascript
复制
ORA-01578: ORACLE data block corrupted (file # 5, block # 1234)
ORA-01110: data file 5: '/u01/oradata/users01.dbf'

后面没有 ABMR 恢复日志。

6.2 模拟物理坏块验证(测试环境)

⚠️ 仅可在测试环境执行!不得在生产环境执行!

代码语言:javascript
复制
# 1. 确定数据文件路径和块号
# 从 V$DATABASE_BLOCK_CORRUPTION 或:
SELECT file_name, file_id FROM DBA_DATA_FILES WHERE tablespace_name ='USERS';

# 2. 在主库使用 dd 损坏一个物理块
# 假设 file_id=5, block_number=12345
# 块大小 8192 字节
dd if=/dev/zero of=/u01/oradata/users01.dbf bs=8192conv=notrunc seek=12344count=1
# ↑ seek = block_number - 1(dd 的 seek 是 0-based)

# 3. 立即查询该表
SELECT COUNT(*) FROM test_table;  -- 预期:ORA-01578

# 4. 检查告警日志
tail -f$ORACLE_BASE/diag/rdbms/<db_name>/trace/alert_*.log | grep-i"automatic block"

# 5. 如果 ABMR 正常工作,会看到请求/恢复日志
# 验证坏块是否消失
SELECT * FROM V$DATABASE_BLOCK_CORRUPTION WHERE FILE# = 5 AND BLOCK# = 12345;
-- 应该无记录(已自动修复)

6.3 通过 V$DATABASE_BLOCK_CORRUPTION 区分坏块类型

代码语言:javascript
复制
SELECT FILE#,
       BLOCK#,
       BLOCKS,
       CORRUPTION_TYPE,
       CORRUPTION_CHANGE#,
       RAC_ID
FROM V$DATABASE_BLOCK_CORRUPTION;

CORRUPTION_TYPE

含义

ABMR 可修复?

FRACTURED

块内容断裂(物理)

CHECKSUM

校验和不匹配(物理)

CORRUPT

通用损坏(可能是物理或逻辑)

❓ 需进一步分析

LOGICAL

逻辑一致性损坏

MEDIUM

介质损坏但校验和正确(逻辑)


7. 逻辑坏块在备库上的正确处理路径

一旦 V$DATABASE_BLOCK_CORRUPTION 中确认损块类型为 LOGICALMEDIUMABMR 路径立即失效,应切换到以下方案之一:

7.1 方案 A:RMAN BLOCKRECOVER(推荐,当有可用备份时)

代码语言:javascript
复制
# 在备库执行 BLOCKRECOVER(修复备库本地坏块)
RMAN> BLOCKRECOVER DATAFILE 5 BLOCK 12345;

工作原理

  • RMAN 从备份(自动或手动指定的备份集)中定位该块备份
  • 若使用存档日志需要恢复到块版本一致性
  • 覆盖备库上的损坏块

优点:不需要主库参与,不依赖主库块的完好性。

限制

  • 需要备库有完整的、未被损坏的 RMAN 备份
  • 无法对 SYSTEM 表空间或 UNDO 表空间的块执行(RMAN 限制)
  • 备份必须是在该逻辑损坏发生之前创建的

7.2 方案 B:DBMS_REPAIR(无备份,非关键数据)

代码语言:javascript
复制
-- 1. 创建 Repair 表
BEGIN
    DBMS_REPAIR.ADMIN_TABLES(
        table_name      =>'REPAIR_TABLE',
        table_type      => DBMS_REPAIR.REPAIR_TABLE,
        action          => DBMS_REPAIR.CREATE_ACTION,
        tablespace_name =>'USERS'
    );
END;
/

-- 2. 检查坏块
DECLARE
    v_num_corrupt INT;
BEGIN
    v_num_corrupt := DBMS_REPAIR.CHECK_OBJECT(
        schema_name    =>'SCOTT',
        object_name    =>'EMP',
        repair_table   =>'REPAIR_TABLE'
    );
    DBMS_OUTPUT.PUT_LINE('Corrupt blocks found: '|| v_num_corrupt);
END;
/

-- 3. 标记块为跳过(丢失该块数据,慎用!)
DECLARE
    v_num_corrupt INT;
BEGIN
    v_num_corrupt := DBMS_REPAIR.FIX_CORRUPT_BLOCKS(
        schema_name    =>'SCOTT',
        object_name    =>'EMP',
        repair_table   =>'REPAIR_TABLE'
    );
    DBMS_OUTPUT.PUT_LINE('Blocks fixed: '|| v_num_corrupt);
END;
/

-- 4. 跳过损坏块读取数据
SELECT/*+ SKIP_CORRUPT */*FROM SCOTT.EMP;

⚠️ DBMS_REPAIR 是在丢失数据的前提下跳过坏块,执行前务必评估数据可丢失性。建议先抢救数据再标记。

7.3 方案 C:索引损坏 — 直接重建

如果逻辑坏块发生在 索引段(最常见的情况):

代码语言:javascript
复制
-- 通过 ANALYZE 或 V$DATABASE_BLOCK_CORRUPTION 确认
SELECT SEGMENT_NAME, SEGMENT_TYPE, PARTITION_NAME, TABLESPACE_NAME
FROM DBA_EXTENTS
WHERE FILE_ID =5
  AND12345BETWEEN BLOCK_ID AND(BLOCK_ID + BLOCKS -1);

-- 如果段类型为 INDEX
DROPINDEX<owner>.<index_name>;
CREATEINDEX<owner>.<index_name>ON<table>(<columns>) ...;

不需要修复坏块本身 — 删除重建索引即可得到无损坏的新索引结构。

7.4 方案 D:通过 CTAS 抢救表数据

对于表段逻辑损坏:

代码语言:javascript
复制
-- 1. 使用 ROWID 分段扫描定位可读记录
-- 先找出坏块对应的 ROWID 范围
-- 2. 跳过坏块 CREATE TABLE AS SELECT
CREATETABLE scott.emp_goodAS
SELECT/*+ SKIP_CORRUPT */*FROM scott.emp;

-- 3. 验证行数
SELECTCOUNT(*)FROM scott.emp_good;
SELECTCOUNT(*)FROM scott.emp;  -- 可能比上面多或少(如果有坏块被跳过)

-- 4. 确认数据完整性后,替换原表
DROPTABLE scott.emp;
ALTERTABLE scott.emp_goodRENAMETO emp;

7.5 方案对比

方案

适用场景

数据丢失率

是否需要 RMAN 备份

复杂度

RMAN BLOCKRECOVER

有可用备份

0%

✅ 需要

DBMS_REPAIR

无备份,非核心表

部分丢失(坏块内数据)

❌ 不需要

索引重建

索引逻辑损坏

0%(数据在表中)

❌ 不需要

CTAS 抢救

表段损坏

坏块内行丢失

❌ 不需要

从主库重建备库

大面积逻辑损坏

取决于恢复点

❌ 不需要


8. 常见误区和 FAQ

误区 1:ABMR 可以修复任何坏块

事实:ABMR 仅修复物理坏块。逻辑坏块(LOGICAL / MEDIUM 类型)永远不会触发 ABMR。

误区 2:只要启用了 Data Guard 就有 ABMR

事实:ABMR 需要 Active Data Guard 许可V$OPTION 返回 TRUE)。仅使用免费 Data Guard(物理备库处于 MOUNT 状态)不支持 ABMR。

误区 3:备库 OPEN_MODE = READ ONLY 就够了

事实:必须是 READ ONLY WITH APPLY。缺了 WITH APPLY 表示没有 Real-Time Apply,MRP 进程不运行,ABMR 初始化失败。

误区 4:只要设置了参数,ABMR 就会自动工作

事实:四个条件缺一不可。最常见的问题是 LOG_ARCHIVE_CONFIG 中漏掉了一端的数据库唯一名称。

误区 5:逻辑坏块可以通过从主库拉取块来解决

事实:逻辑坏块可能是因为 Redo 损坏或 Oracle Bug 导致,主库上的同一块也可能已损坏,或备库重放 Redo 后同样损坏。ABMR 不尝试逻辑坏块修复。


9. 主动预防与监控建议

9.1 定期检测坏块

代码语言:javascript
复制
-- RMAN 物理与逻辑检测
RMAN> BACKUP VALIDATE CHECK LOGICAL DATABASE;
-- 或
RMAN> VALIDATE CHECK LOGICAL DATABASE;

-- DBVERIFY
$ dbv file=/u01/oradata/users01.dbf blocksize=8192 logonly=yes

9.2 监控 ABMR 活动

代码语言:javascript
复制
-- 查看 ABMR 相关的统计信息
SELECT NAME,VALUE
FROM V$SYSSTAT
WHERE NAME LIKE'%automatic block%';

-- Active Data Guard 统计
SELECT NAME,VALUE, TIME_COMPUTED
FROM V$ADG_STATS
WHERE NAME LIKE'%block%';

9.3 确保 ABMR 条件持续满足

建议加入日常巡检脚本:

代码语言:javascript
复制
-- ABMR 条件巡检脚本
COLUMNcondition FORMAT A50
COLUMNstatus FORMAT A20

SELECT'Open Mode'AScondition,
       CASEWHEN OPEN_MODE ='READ ONLY WITH APPLY'THEN'✅ PASS'ELSE'❌ FAIL'ENDASstatus
FROM V$DATABASE
UNIONALL
SELECT'MRP0 Process',
       CASEWHENEXISTS(SELECT1FROM V$MANAGED_STANDBY WHERE PROCESS ='MRP0'ANDSTATUS='APPLYING_LOG')
            THEN'✅ PASS'ELSE'❌ FAIL'END
FROMDUAL
UNIONALL
SELECT'ADG License',
       CASEWHEN(SELECTVALUEFROM V$OPTION WHERE PARAMETER ='Active Data Guard')='TRUE'
            THEN'✅ PASS'ELSE'❌ FAIL'END
FROMDUAL
UNIONALL
SELECT'LOG_ARCHIVE_CONFIG',
       CASEWHEN(SELECTVALUEFROM V$PARAMETER WHERE NAME ='log_archive_config')LIKE'%DG_CONFIG=%'
            THEN'✅ CHECK (manual verify both sides)'ELSE'❌ FAIL'END
FROMDUAL;
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ByteHouse 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 文档目的
  • 2. Automatic Block Media Recovery (ABMR)
    • 核心工作流程
  • 3. ABMR 生效的四个硬性前提条件
    • 条件 1:备库 OPEN_MODE 必须为 READ ONLY WITH APPLY
    • 条件 2:MRP0 进程必须处于 APPLYING_LOG 状态
    • 条件 3:Active Data Guard 许可必须为 TRUE
    • 条件 4:LOG_ARCHIVE_CONFIG 必须在主备两端都包含完整的 DG 名称
  • 4. 物理坏块 vs 逻辑坏块 — 本质区别
    • 4.1 物理坏块(Physical Corruption)
    • 4.2 逻辑坏块(Logical Corruption)
    • 4.3 对比总结
  • 5. 逻辑坏块为什么无法触发 ABMR — 深入解析
    • 5.1 根因:逻辑损坏可能在备库上同样存在
    • 5.2 ABMR 的防御机制
  • 6. 验证 ABMR 是否真正在工作(而不是你以为它在工作)
    • 6.1 通过告警日志验证
    • 6.2 模拟物理坏块验证(测试环境)
    • 6.3 通过 V$DATABASE_BLOCK_CORRUPTION 区分坏块类型
  • 7. 逻辑坏块在备库上的正确处理路径
    • 7.1 方案 A:RMAN BLOCKRECOVER(推荐,当有可用备份时)
    • 7.2 方案 B:DBMS_REPAIR(无备份,非关键数据)
    • 7.3 方案 C:索引损坏 — 直接重建
    • 7.4 方案 D:通过 CTAS 抢救表数据
    • 7.5 方案对比
  • 8. 常见误区和 FAQ
    • 误区 1:ABMR 可以修复任何坏块
    • 误区 2:只要启用了 Data Guard 就有 ABMR
    • 误区 3:备库 OPEN_MODE = READ ONLY 就够了
    • 误区 4:只要设置了参数,ABMR 就会自动工作
    • 误区 5:逻辑坏块可以通过从主库拉取块来解决
  • 9. 主动预防与监控建议
    • 9.1 定期检测坏块
    • 9.2 监控 ABMR 活动
    • 9.3 确保 ABMR 条件持续满足
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档