Oracle DBMS_REPAIR 修复损坏块
Oracle DBMS_REPAIR 修复损坏块
适用版本:Oracle Database 8i / 9i / 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
DBMS_REPAIR 包用于检测和修复数据块损坏[1]:
核心功能:
- 检测损坏块
- 标记损坏块
- 跳过损坏块
- 重建空闲列表
限制:
- 不能恢复损坏块中的数据
- 仅让数据库继续运行
2. 检测损坏块
2.1 RMAN 检测
-- 1. RMAN 验证
RMAN> BACKUP VALIDATE CHECK LOGICAL DATABASE;
-- 2. 查看损坏
SELECT * FROM v$database_block_corruption;
2.2 DBV 工具
# 验证数据文件
dbv file=/u01/oradata/orcl/users01.dbf blocksize=8192
# 输出示例:
# DBVERIFY: Verification complete
# Total Pages Examined : 12800
# Total Pages Processed (Data) : 10000
# Total Pages Failing (Data) : 5
2.3 ANALYZE 验证
-- 验证表
ANALYZE TABLE scott.employees VALIDATE STRUCTURE;
-- 验证索引
ANALYZE INDEX scott.emp_idx VALIDATE STRUCTURE;
3. DBMS_REPAIR 流程
3.1 创建修复表
-- 1. 创建修复表
BEGIN
DBMS_REPAIR.ADMIN_TABLES(
table_name => 'REPAIR_TABLE',
table_type => DBMS_REPAIR.REPAIR_TABLE,
action => DBMS_REPAIR.CREATE_ACTION,
tablespace => 'USERS'
);
END;
/
-- 2. 创建孤立项表
BEGIN
DBMS_REPAIR.ADMIN_TABLES(
table_name => 'ORPHAN_TABLE',
table_type => DBMS_REPAIR.ORPHAN_TABLE,
action => DBMS_REPAIR.CREATE_ACTION,
tablespace => 'USERS'
);
END;
/
3.2 检测损坏
-- 检测损坏对象
SET SERVEROUTPUT ON
DECLARE
num_corrupt INT;
BEGIN
DBMS_REPAIR.CHECK_OBJECT(
schema_name => 'SCOTT',
object_name => 'EMPLOYEES',
repair_table_name => 'REPAIR_TABLE',
corrupt_count => num_corrupt
);
DBMS_OUTPUT.PUT_LINE('Number corrupt: ' || num_corrupt);
END;
/
3.3 查看损坏
-- 查看损坏块
SELECT
object_name,
block_id,
corrupt_type,
marked_corrupt
FROM repair_table;
3.4 标记损坏块
-- 标记为损坏
SET SERVEROUTPUT ON
DECLARE
num_fix INT;
BEGIN
DBMS_REPAIR.FIX_CORRUPT_BLOCKS(
schema_name => 'SCOTT',
object_name => 'EMPLOYEES',
object_type => DBMS_REPAIR.TABLE_OBJECT,
repair_table_name => 'REPAIR_TABLE',
fix_count => num_fix
);
DBMS_OUTPUT.PUT_LINE('Number fix: ' || num_fix);
END;
/
3.5 跳过损坏块
-- 设置跳过损坏块
BEGIN
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(
schema_name => 'SCOTT',
object_name => 'EMPLOYEES',
object_type => DBMS_REPAIR.TABLE_OBJECT,
flags => DBMS_REPAIR.SKIP_FLAG
);
END;
/
-- 取消跳过
BEGIN
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(
schema_name => 'SCOTT',
object_name => 'EMPLOYEES',
object_type => DBMS_REPAIR.TABLE_OBJECT,
flags => DBMS_REPAIR.NOSKIP_FLAG
);
END;
/
3.6 重建空闲列表
-- 重建 FREELISTS
BEGIN
DBMS_REPAIR.REBUILD_FREELISTS(
schema_name => 'SCOTT',
object_name => 'EMPLOYEES',
object_type => DBMS_REPAIR.TABLE_OBJECT
);
END;
/
3.7 查找孤立项
-- 查找索引中的孤立项
SET SERVEROUTPUT ON
DECLARE
num_orphan INT;
BEGIN
DBMS_REPAIR.DUMP_ORPHAN_KEYS(
schema_name => 'SCOTT',
object_name => 'EMP_IDX',
object_type => DBMS_REPAIR.INDEX_OBJECT,
repair_table_name => 'REPAIR_TABLE',
orphan_table_name => 'ORPHAN_TABLE',
key_count => num_orphan
);
DBMS_OUTPUT.PUT_LINE('Number orphan: ' || num_orphan);
END;
/
4. 块介质恢复(BMR)
4.1 RMAN BMR
-- 1. 查看损坏块
SELECT * FROM v$database_block_corruption;
-- 2. 恢复单个块
RMAN> RECOVER DATAFILE 5 BLOCK 123;
-- 3. 恢复所有损坏块
RMAN> RECOVER CORRUPTION LIST;
4.2 BMR 优势
- 在线恢复
- 仅恢复损坏块
- 业务影响最小
- 无需关闭数据库
5. 损坏块处理流程
1. 检测损坏块
- RMAN VALIDATE
- DBV
- ANALYZE
2. 评估损坏
- 查询 repair_table
- 确定影响范围
3. 尝试 BMR
- RMAN RECOVER
- 优先使用
4. 若 BMR 失败
- DBMS_REPAIR.FIX_CORRUPT_BLOCKS
- DBMS_REPAIR.SKIP_CORRUPT_BLOCKS
5. 恢复数据
- 从备份恢复
- 从其他源补充
- 重建索引
6. 验证
- 再次检测
- 业务验证
6. 常见场景
6.1 单块损坏
-- 1. BMR 恢复
RMAN> RECOVER DATAFILE 5 BLOCK 123;
-- 2. 验证
SELECT * FROM scott.employees WHERE rowid = DBMS_ROWID.ROWID_CREATE(1, 5, 123, 0, 0);
6.2 多块损坏
-- 1. 查看所有损坏
SELECT * FROM v$database_block_corruption;
-- 2. 批量恢复
RMAN> RECOVER CORRUPTION LIST;
6.3 索引损坏
-- 1. 重建索引
ALTER INDEX scott.emp_idx REBUILD;
-- 2. 验证
ANALYZE INDEX scott.emp_idx VALIDATE STRUCTURE;
7. 监控损坏
7.1 v$database_block_corruption
SELECT
file#,
block#,
blocks,
corruption_change#,
corruption_type
FROM v$database_block_corruption;
7.2 corruption_type
| 类型 | 说明 |
|---|---|
| ALL ZERO | 块全零 |
| FRACTURED | 块头不匹配 |
| CHECKSUM | 校验和错误 |
| CORRUPT | 损坏 |
| LOGICAL | 逻辑损坏 |
7.3 Alert Log
# 监控 alert log 中的 ORA-01578
grep "ORA-01578" $ORACLE_BASE/diag/rdbms/$DB_UNIQUE_NAME/$ORACLE_SID/trace/alert_$ORACLE_SID.log
8. 常见坑与排错
8.1 ORA-01578: 数据块损坏
修复:
-- 1. 查看损坏块
SELECT * FROM v$database_block_corruption;
-- 2. BMR 恢复
RMAN> RECOVER DATAFILE <file#> BLOCK <block#>;
-- 3. 或使用 DBMS_REPAIR
8.2 ORA-00600: 内部错误
修复:
# 1. 查看 trace 文件
cat $ORACLE_BASE/diag/rdbms/$DB_UNIQUE_NAME/$ORACLE_SID/trace/*ora*.trc
# 2. 联系 Oracle Support
# 3. 提供错误参数和 trace
8.3 BMR 失败
修复:
-- 1. 检查备份
RMAN> LIST BACKUP OF DATAFILE 5;
-- 2. 使用 DBMS_REPAIR
-- 3. 从其他源恢复数据
8.4 损坏块数据丢失
修复:
-- 1. 从备份恢复部分数据
-- 2. 从其他系统补充
-- 3. 重建索引
ALTER INDEX scott.emp_idx REBUILD;
8.5 跳过损坏块后查询异常
修复:
-- 1. 检查跳过状态
SELECT owner, table_name, skip_corrupt
FROM dba_tables
WHERE owner='SCOTT' AND table_name='EMPLOYEES';
-- 2. 取消跳过(恢复后)
BEGIN
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(
schema_name => 'SCOTT',
object_name => 'EMPLOYEES',
object_type => DBMS_REPAIR.TABLE_OBJECT,
flags => DBMS_REPAIR.NOSKIP_FLAG
);
END;
/
9. 最佳实践
- 优先 BMR:RMAN RECOVER
- BMR 失败用 DBMS_REPAIR:标记跳过
- 定期 RMAN VALIDATE:检测损坏
- 监控 v$database_block_corruption:及时发现
- 备份关键表:数据保护
- 重建索引:损坏后修复
- 联系 Oracle Support:严重问题
- 测试恢复:验证流程
- 保留 trace 文件:分析原因
- 硬件检查:底层问题
10. 参考资料
[1] Oracle Database Administrator’s Guide 19c, “DBMS_REPAIR” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/
[2] Oracle Database PL/SQL Packages and Types Reference 19c, “DBMS_REPAIR” https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/