
Oracle块介质恢复(Block Media Recovery)与块损坏自动修复
一、BMR概述与核心概念
官方解释
块介质恢复(Block Media Recovery, BMR) 是Oracle数据库提供的一种高级恢复技术,它允许在数据块级别进行精确修复,而无需恢复整个数据文件。当少数数据块发生损坏时,BMR通过RMAN(Recovery Manager)从有效备份中提取完好的块副本,并应用从损坏发生时刻到当前的所有相关重做日志,在块级别进行前滚恢复。
自动检测机制通过V$DATABASE_BLOCK_CORRUPTION视图实时监控和记录块损坏信息,结合RMAN的BLOCKRECOVER命令实现损坏块的自动识别和修复,体现了Oracle数据库的自愈能力。
通俗解释
将BMR想象成一个精准的医疗修复过程:
- 传统恢复:像为了治疗一个小伤口而更换整个器官(恢复整个数据文件)
- 块介质恢复:像微创手术,只精确修复受损的组织(数据块),不影响健康部分
Oracle的自动检测机制就像身体的免疫系统,能够:
- 自动发现"病变"数据块(通过
V$DATABASE_BLOCK_CORRUPTION) - 从"基因库"(备份)中提取健康细胞(完好的块副本)
- 应用"生长因子"(重做日志)使细胞更新到最新状态
- 完成精准修复,不影响其他健康组织
二、块损坏检测与诊断机制
1. 块损坏类型与检测
Oracle通过多种机制检测块损坏:
-- 查看数据库中的块损坏情况
SELECT * FROM V$DATABASE_BLOCK_CORRUPTION;
-- 查看详细的块损坏信息
SELECT file#, block#, blocks, corruption_type, corruption_description
FROM V$DATABASE_BLOCK_CORRUPTION
ORDER BY file#, block#;
块损坏类型:
- 物理损坏:磁盘扇区损坏,校验和不匹配
- 逻辑损坏:块内部结构不一致,如行片断错误
- 介质损坏:存储硬件故障导致的损坏
2. 自动检测机制
Oracle通过多种后台进程自动检测块损坏:
三、BMR内部工作原理
1. BMR恢复流程
块介质恢复的完整流程:
-- RMAN执行块恢复的底层操作
1. 识别损坏块:SELECT * FROM V$DATABASE_BLOCK_CORRUPTION;
2. 定位备份:从RMAN目录中找到包含完好块的备份集
3. 提取块副本:从备份中恢复完好的块到内存
4. 应用重做:从归档日志和在线重做日志中应用所有相关更改
5. 写回数据文件:将修复后的块写回数据文件
6. 验证修复:重新验证块的完整性
2. 重做日志应用机制
BMR智能地应用所需的重做日志:
-- 确定需要应用的重做日志范围
SELECT MIN(first_change#) first_scn, MAX(next_change#) last_scn
FROM V$ARCHIVED_LOG
WHERE sequence# BETWEEN :start_seq AND :end_seq;
-- 查看块恢复所需的归档日志
SELECT thread#, sequence#, first_change#, next_change#
FROM V$ARCHIVED_LOG
WHERE first_change# <= :corrupt_scn
AND next_change# > :corrupt_scn;
四、自动修复实现机制
1. RMAN BLOCKRECOVER命令
-- 基本块恢复语法
RMAN> BLOCKRECOVER DATAFILE 7 BLOCK 5, 12, 23;
-- 恢复所有损坏的块
RMAN> BLOCKRECOVER CORRUPTION LIST;
-- 从特定备份恢复
RMAN> BLOCKRECOVER DATAFILE 3 BLOCK 17 FROM TAG 'weekly_backup';
-- 并行恢复多个块
RMAN> BLOCKRECOVER DATAFILE 2 BLOCK 12, 13, 14 DATAFILE 3 BLOCK 5, 6;
2. 自动修复触发机制
Oracle提供多种自动修复触发方式:
-- 1. 配置自动块修复参数
ALTER SYSTEM SET db_ultra_safe = ON; -- 启用高级数据保护
ALTER SYSTEM SET db_block_checking = TRUE; -- 启用块检查
ALTER SYSTEM SET db_block_checksum = TYPICAL; -- 启用校验和
-- 2. 设置自动修复作业
BEGIN
DBMS_SCHEDULER.create_job(
job_name => 'AUTO_BLOCK_RECOVERY',
job_type => 'PLSQL_BLOCK',
job_action => '
BEGIN
-- 检查并修复损坏块
FOR corrupt_rec IN (SELECT file#, block# FROM V$DATABASE_BLOCK_CORRUPTION)
LOOP
-- 调用RMAN进行块恢复
DBMS_RMAN.BLOCKRECOVER(
file_id => corrupt_rec.file#,
block_id => corrupt_rec.block#
);
END LOOP;
END;',
start_date => SYSDATE,
repeat_interval => 'FREQ=HOURLY',
enabled => TRUE
);
END;
/
五、监控与诊断视图
1. 关键数据字典视图
-- 查看块损坏历史
SELECT * FROM V$DATABASE_BLOCK_CORRUPTION;
-- 监控块恢复进度
SELECT * FROM V$BLOCK_RECOVERY_STATUS;
-- 查看数据文件块状态
SELECT file_id, block_id, blocks, status
FROM DBA_EXTENTS
WHERE file_id = :file_id
AND block_id BETWEEN :start_block AND :end_block;
-- 检查块恢复统计信息
SELECT * FROM V$BLOCK_RECOVERY_STATS;
2. 等待事件与性能诊断
-- 查看块恢复相关等待事件
SELECT event, total_waits, time_waited
FROM V$SYSTEM_EVENT
WHERE event LIKE '%block%recover%' OR event LIKE '%media%recover%'
ORDER BY time_waited DESC;
-- 关键等待事件:
-- block recovery wait
-- media recovery wait
-- recovery read wait
-- 监控RMAN恢复会话
SELECT sid, serial#, context, sofar, totalwork,
ROUND(sofar/totalwork*100, 2) percent_complete
FROM V$SESSION_LONGOPS
WHERE opname LIKE '%RMAN%' OR opname LIKE '%Block%Recovery%';
六、常见问题与解决方案
1. 块损坏无法自动修复
问题现象:块损坏检测到但自动修复失败
排查方法:
-- 检查损坏块详细信息
SELECT file#, block#, corruption_type, corruption_description
FROM V$DATABASE_BLOCK_CORRUPTION;
-- 检查备份可用性
SELECT backup_type, file#, block_size, blocks, status
FROM V$BACKUP_DATAFILE
WHERE file# = :corrupt_file;
-- 验证归档日志完整性
SELECT sequence#, first_change#, next_change#, archived, applied
FROM V$ARCHIVED_LOG
WHERE first_change# <= :corrupt_scn
AND next_change# > :corrupt_scn;
解决方案:
-- 1. 手动执行块恢复
RMAN> RUN {
SET NEWNAME FOR DATAFILE 5 TO '+DATA/NEWDB/DATAFILE/users01.dbf';
BLOCKRECOVER DATAFILE 5 BLOCK 123;
}
-- 2. 使用数据泵导出/导入受影响数据
EXPDP system/password TABLES=scott.emp QUERY=\"WHERE DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)=123\"
2. 系统表空间块损坏
问题现象:系统表空间关键块损坏
排查方法:
-- 检查系统表空间损坏
SELECT file#, block#, corruption_type
FROM V$DATABASE_BLOCK_CORRUPTION
WHERE file# IN (SELECT file# FROM V$DATAFILE WHERE name LIKE '%system%');
-- 评估损坏影响
SELECT segment_type, segment_name, partition_name
FROM DBA_EXTENTS
WHERE file_id = :file_id
AND :block_id BETWEEN block_id AND block_id + blocks - 1;
解决方案:
-- 系统表空间损坏需要特殊处理
-- 可能需要启动到mount状态进行恢复
STARTUP MOUNT;
RMAN> BLOCKRECOVER DATAFILE 1 BLOCK 17;
ALTER DATABASE OPEN;
3. 块恢复性能问题
问题现象:块恢复过程缓慢,影响系统性能
排查方法:
-- 监控恢复性能
SELECT * FROM V$RECOVERY_PROGRESS;
-- 检查I/O性能
SELECT * FROM V$BACKUP_ASYNC_IO WHERE STATUS = 'IN PROGRESS';
SELECT * FROM V$RECOVERY_READ_IO WHERE STATUS = 'IN PROGRESS';
-- 检查归档日志应用速率
SELECT * FROM V$RECOVERY_RATE;
解决方案:
-- 调整恢复并行度
RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 4;
-- 增加恢复缓冲区大小
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 100G;
-- 优化归档日志访问
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1 = 'LOCATION=+FAST_DISK/archive';
七、最佳实践与配置示例
1. 预防性配置
-- 启用块检查和完善性验证
ALTER SYSTEM SET db_block_checking = TRUE; -- 检查逻辑一致性
ALTER SYSTEM SET db_block_checksum = TYPICAL; -- 启用物理校验和
ALTER SYSTEM SET db_lost_write_protect = TYPICAL; -- 防止丢失写
-- 配置定期块验证
RMAN> CONFIGURE VALIDATION POLICY CHECK BLOCK;
-- 设置定期RMAN验证
RMAN> VALIDATE DATABASE CHECK LOGICAL;
2. 自动化恢复脚本
-- 创建自动块恢复过程
CREATE OR REPLACE PROCEDURE auto_block_recovery AS
CURSOR corrupt_blocks IS
SELECT file#, block#, corruption_type
FROM V$DATABASE_BLOCK_CORRUPTION
WHERE repair_timestamp IS NULL;
BEGIN
FOR block_rec IN corrupt_blocks LOOP
BEGIN
-- 记录恢复开始
INSERT INTO block_recovery_log
VALUES (block_rec.file#, block_rec.block#, SYSDATE, 'STARTED');
-- 执行块恢复
DBMS_RMAN.BLOCKRECOVER(
file_id => block_rec.file#,
block_id => block_rec.block#
);
-- 记录恢复成功
UPDATE block_recovery_log
SET status = 'COMPLETED', end_time = SYSDATE
WHERE file_id = block_rec.file# AND block_id = block_rec.block#;
EXCEPTION
WHEN OTHERS THEN
-- 记录恢复失败
UPDATE block_recovery_log
SET status = 'FAILED', error_message = SQLERRM, end_time = SYSDATE
WHERE file_id = block_rec.file# AND block_id = block_rec.block#;
END;
END LOOP;
END;
/
-- 安排定期执行
BEGIN
DBMS_SCHEDULER.create_job(
job_name => 'DAILY_BLOCK_RECOVERY',
job_type => 'STORED_PROCEDURE',
job_action => 'AUTO_BLOCK_RECOVERY',
start_date => SYSDATE,
repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0',
enabled => TRUE
);
END;
/
3. 监控与警报配置
-- 创建块损坏监控视图
CREATE VIEW block_corruption_monitor AS
SELECT file_id, block_id, tablespace_name, segment_name,
corruption_type, detection_time, repair_time,
CASE WHEN repair_time IS NULL THEN 'UNREPAIRED' ELSE 'REPAIRED' END status
FROM V$DATABASE_BLOCK_CORRUPTION c
JOIN DBA_EXTENTS e ON (c.file# = e.file_id AND c.block# = e.block_id);
-- 设置块损坏警报
BEGIN
DBMS_SERVER_ALERT.SET_THRESHOLD(
metrics_id => DBMS_SERVER_ALERT.BLOCK_CORRUPTION,
warning_operator => DBMS_SERVER_ALERT.OPERATOR_GT,
warning_value => '0',
critical_operator => DBMS_SERVER_ALERT.OPERATOR_GT,
critical_value => '5',
observation_period => 1,
consecutive_occurrences => 1
);
END;
/
八、实战场景分析
场景1:在线生产数据库块损坏
问题:生产数据库报告ORA-01578错误,但数据库仍在运行
解决方案:
-- 1. 确认损坏块信息
SELECT file#, block#, corruption_type
FROM V$DATABASE_BLOCK_CORRUPTION;
-- 2. 确定受影响对象
SELECT segment_type, owner, segment_name
FROM DBA_EXTENTS
WHERE file_id = :file_id AND :block_id BETWEEN block_id AND block_id + blocks - 1;
-- 3. 在线修复损坏块
RMAN> BLOCKRECOVER DATAFILE :file_id BLOCK :block_id;
-- 4. 验证修复结果
SELECT * FROM V$DATABASE_BLOCK_CORRUPTION
WHERE file# = :file_id AND block# = :block_id;
场景2:大规模块损坏恢复
问题:存储故障导致多个数据文件出现块损坏
解决方案:
-- 1. 评估损坏范围
SELECT file#, COUNT(*) corrupt_blocks
FROM V$DATABASE_BLOCK_CORRUPTION
GROUP BY file#
ORDER BY COUNT(*) DESC;
-- 2. 批量恢复损坏块
RMAN> RUN {
SET MAXCORRUPT FOR DATAFILE 3 TO 100;
BLOCKRECOVER CORRUPTION LIST;
}
-- 3. 监控恢复进度
SELECT * FROM V$SESSION_LONGOPS
WHERE opname LIKE '%Block%Recovery%';
-- 4. 生成恢复报告
SELECT file#, block#, recovery_time, status
FROM V$BLOCK_RECOVERY_HISTORY
WHERE recovery_time > SYSDATE - 1;
九、总结
Oracle块介质恢复(BMR)技术体现了数据库自愈能力的先进水平,其主要优势包括:
- 精准修复:在块级别进行恢复,不影响整个数据文件或其他数据块
- 在线操作:大多数情况下无需停机,支持在线修复
- 自动检测:通过
V$DATABASE_BLOCK_CORRUPTION自动发现和记录损坏 - 智能恢复:自动选择最佳备份源和应用必要的重做日志
- 全面监控:提供完整的监控和诊断能力
关键成功因素:
- 有效备份:BMR依赖可用的有效备份,必须确保备份策略的完整性
- 日志保护:需要完整的归档日志和在线重做日志支持
- 定期验证:通过RMAN VALIDATE定期检查数据块完整性
- 监控警报:设置适当的监控和警报机制,及时发现和处理损坏
通过合理配置BMR和相关的自动化机制,可以显著提高数据库的可用性和可靠性,减少因块损坏导致的停机时间,真正实现数据库的自愈能力。
欢迎关注我的公众号《IT小Chen》

被折叠的 条评论
为什么被折叠?



