热衷于分享各种干货知识,大家有想看或者想学的可以评论区留言,秉承着“开源知识来源于互联网,回归于互联网”的理念,分享一些日常工作中能用到或者比较重要的内容,希望大家能够喜欢,不足之处请大家多提宝贵地意见,我们一起提升,守住自己的饭碗。
关注公众号,技术道路不迷路

一、Oracle数据库坏块概述
1.1 什么是数据库坏块
Oracle数据库的数据块遵循固定的格式与结构,分为Cache Layer(缓存层)、Transaction Layer(事务层) 和Data Layer(数据层) 三层。数据库在对数据块执行读写操作时,会自动进行一致性检查,包括验证数据块的类型、地址信息、SCN号(系统更改号)以及头部与尾部的匹配性。若检查发现信息不一致,该数据块将被标记为“坏块”。
1.2 坏块的类型
根据损坏本质,坏块可分为两大类:
• 物理坏块(介质坏块):数据块本身因存储介质故障而损坏,无法被正常读取。例如磁盘磁道损坏导致块内容丢失、块头信息被破坏等。 • 逻辑坏块:数据块物理上完整(可被读取),但内容存在逻辑不一致性。例如行记录与索引条目不匹配、事务状态异常等。
1.3 坏块对数据库的影响
坏块会触发数据库异常,主要表现为:
1. 错误日志提示:告警日志中常见以下错误代码: • ORA-01578:数据块损坏核心错误 • ORA-01110:数据文件访问失败(关联坏块) • ORA-00600:Oracle内部错误(第一个参数为2000-8000时多与坏块相关)。 2. 对象受影响范围: • 系统级对象:数据字典表、回滚段、临时段等(可能导致数据库启动失败); • 用户级对象:用户数据表、索引、LOB段等(导致查询/写入失败、数据丢失)。
二、坏块产生的原因
坏块的根源涉及硬件、软件、操作等多个层面,主要包括:
1. 硬件问题:磁盘驱动器故障、存储控制器损坏、内存芯片故障(导致数据读写混乱)。 2. 操作系统问题:I/O调用异常、内核BUG、文件系统缓存机制失效。 3. 内存/分页问题:内存地址冲突、虚拟内存分页错误导致数据块内容篡改。 4. 磁盘工具不当使用:第三方磁盘修复工具误修改Oracle数据文件结构。 5. 存储问题:数据文件被意外覆盖、存储阵列RAID配置错误、存储空间溢出。 6. Oracle软件BUG:特定版本Oracle的I/O处理模块缺陷(需通过补丁修复)。 7. 非Oracle进程干扰:外部进程非法访问Oracle的SGA(共享内存区域),破坏数据块缓存。 8. 异常关机:突然断电、强制kill数据库进程,导致数据块未完成写入而不完整。
三、坏块的预防措施
预防是避免坏块影响的核心,需从“主动检查”“参数优化”“硬件维护”三方面入手:
3.1 定期检查与更新
• 关注Oracle官方支持网站(Metalink/MOS)的“已知问题列表”,及时了解潜在风险; • 定期安装Oracle发布的安全补丁和PSU(数据库补丁集),修复已知BUG。
3.2 启用验证工具
通过工具定期校验数据块完整性,提前发现潜在坏块:
1. RMAN验证:通过备份验证命令检查数据文件一致性(支持逻辑校验): RMAN> BACKUP CHECK LOGICAL VALIDATE DATAFILE <文件号>;2. DBVERIFY工具:独立于数据库实例的物理文件校验工具: dbv file=<数据文件路径> blocksize=<块大小> logfile=<日志路径>3. ANALYZE命令:校验表及索引的结构一致性: ANALYZE TABLE <表名> VALIDATE STRUCTURE CASCADE; -- CASCADE同时校验索引4. EXP/EXPDP导出:通过全量/对象导出间接校验数据可读性,导出失败常提示坏块。
3.3 参数配置优化
通过调整数据库参数增强坏块检测能力:
• db_block_checksum = TRUE
(默认开启):写入数据块时计算校验和,读取时验证(检测物理坏块);• db_block_checking = FULL
:启用数据块逻辑一致性检查(检测逻辑坏块,对性能有轻微影响,建议核心库启用)。
3.4 硬件与系统维护
• 定期通过存储管理工具(如EMC Unisphere、IBM Spectrum)检查磁盘/阵列健康状态; • 禁止在数据库服务器上运行无关进程(如文件下载、压缩工具); • 严格执行正常关机流程( shutdown immediate
),避免强制断电;• 配置UPS(不间断电源),降低突发断电风险。
四、坏块的检测与诊断
当数据库出现异常时,需按步骤定位坏块:
4.1 识别坏块症状
• 应用程序报“ORA-01578”“ORA-01110”错误; • 告警日志( alert_<实例名>.log
)中出现“Corrupt block dba”(损坏块地址);• 后台进程(DBWR、LGWR、SMON)出现“buffer busy waits”等异常等待事件; • Trace文件(告警日志中会提示路径)详细记录坏块信息。
4.2 收集坏块关键信息
从告警日志或Trace文件中提取以下核心信息,为后续处理提供依据:
• 文件号:AFN(绝对文件号)或RFN(相对文件号); • 块号:坏块在数据文件中的偏移块号; • SCN信息:坏块最后修改的SCN(用于恢复时间点定位)。
4.3 确定受影响的对象
通过dba_extents
视图查询坏块所属的数据库对象:
SELECT tablespace_name, -- 表空间名
segment_type, -- 段类型(TABLE/INDEX/ROLLBACK)
owner, -- 所有者
segment_name, -- 对象名
partition_name -- 分区名(若有)
FROM dba_extents
WHERE file_id = <坏块所属文件号>
AND <坏块号> BETWEEN block_id AND block_id + blocks - 1;
注意:临时文件中的坏块不会返回结果(临时段会自动重建)。
五、坏块的处理方法
坏块处理需根据“是否有备份”“坏块类型”“受影响对象”选择方案,核心原则是“优先恢复,其次跳过/重建”。
5.1 基于备份的数据文件恢复(归档模式下)
若数据库运行在归档模式且有完整备份,可通过以下步骤恢复受影响的数据文件:
1. 将数据文件离线: ALTER DATABASE DATAFILE '<数据文件路径>' OFFLINE;2. (可选)若数据文件物理损坏,先重命名: ALTER DATABASE RENAME FILE '<旧路径>' TO '<新路径>';3. 恢复数据文件(从RMAN备份或冷备份恢复): RECOVER DATAFILE '<数据文件路径>';4. 将数据文件在线: ALTER DATABASE DATAFILE '<数据文件路径>' ONLINE;
5.2 RMAN块级恢复(Oracle 9i及以上)
针对少量坏块,无需恢复整个数据文件,可通过RMAN直接恢复坏块:
1. 校验坏块并确认信息: -- 校验指定数据文件
RMAN> BACKUP VALIDATE DATAFILE <文件号>;
-- 查看坏块列表
SELECT * FROM v$database_block_corruption WHERE file# = <文件号>;2. 恢复指定坏块: RMAN> BLOCKRECOVER DATAFILE <文件号> BLOCK <块号> FROM BACKUPSET;
5.3 ROWID范围扫描保存数据(无备份时)
若表出现坏块且无备份,可通过ROWID分段查询跳过坏块,保存有效数据:
1. 创建临时表存储有效数据: CREATE TABLE <临时表名> AS SELECT * FROM <损坏表名> WHERE 1=2; -- 复制结构2. 按ROWID范围插入有效数据(需先确定坏块对应的ROWID范围): -- 插入坏块前的数据
INSERT INTO <临时表名> SELECT * FROM <损坏表名> WHERE rowid < '<坏块起始ROWID>';
-- 插入坏块后的数据
INSERT INTO <临时表名> SELECT * FROM <损坏表名> WHERE rowid >= '<坏块结束ROWID>';3. 重建原表(删除损坏表,将临时表重命名)。
5.4 10231事件跳过坏块(临时应急)
通过设置10231事件,让数据库全表扫描时跳过坏块(仅适用于临时导出数据,不修复坏块):
1. Session级别设置(仅当前会话生效): ALTER SESSION SET EVENTS '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10';2. 数据库级别设置(需重启生效,不建议长期使用):
在init.ora
或spfile
中添加:event="10231 trace name context forever, level 10"3. 导出有效数据: CREATE TABLE <临时表名> AS SELECT * FROM <损坏表名>;
5.5 DBMS_REPAIR包修复(逻辑/物理坏块)
Oracle提供DBMS_REPAIR
系统包专门处理坏块,步骤如下:
1. 创建修复管理表(存储坏块信息): BEGIN
DBMS_REPAIR.ADMIN_TABLES(
table_name => 'REPAIR_TABLE', -- 坏块信息表
table_type => DBMS_REPAIR.REPAIR_TABLE,
action => DBMS_REPAIR.CREATE_ACTION,
tablespace => '<表空间名>'
);
DBMS_REPAIR.ADMIN_TABLES(
table_name => 'ORPHAN_TABLE', -- 孤立索引条目表
table_type => DBMS_REPAIR.ORPHAN_TABLE,
action => DBMS_REPAIR.CREATE_ACTION,
tablespace => '<表空间名>'
);
END;
/2. 检查坏块: DECLARE
corrupt_count NUMBER; -- 坏块数量
BEGIN
DBMS_REPAIR.CHECK_OBJECT(
schema_name => '<所有者>',
object_name => '<损坏对象名>',
repair_table_name => 'REPAIR_TABLE',
corrupt_count => corrupt_count
);
DBMS_OUTPUT.PUT_LINE('坏块数量:' || corrupt_count);
END;
/3. 修复坏块(标记为“软件损坏”,避免被访问): DECLARE
fix_count NUMBER; -- 修复数量
BEGIN
DBMS_REPAIR.FIX_CORRUPT_BLOCKS(
schema_name => '<所有者>',
object_name => '<损坏对象名>',
fix_count => fix_count
);
DBMS_OUTPUT.PUT_LINE('修复数量:' || fix_count);
END;
/4. 跳过坏块(允许查询时忽略坏块): EXEC DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('<所有者>', '<损坏对象名>');5. 重建自由列表(修复后整理空间): EXEC DBMS_REPAIR.REBUILD_FREELISTS('<所有者>', '<损坏对象名>');
5.6 EXP/IMP工具恢复(无备份时)
结合10231事件,通过导出/导入工具重建损坏对象:
1. 启用10231事件跳过坏块; 2. 导出损坏对象: exp <用户名>/<密码> file=<导出文件.dmp> tables=<损坏表名>3. 删除损坏表,重新导入数据: imp <用户名>/<密码> file=<导出文件.dmp> tables=<损坏表名>
六、特殊对象的坏块处理
特殊对象(系统表空间、回滚段等)的坏块可能导致数据库无法启动,需特殊处理:
6.1 系统表空间坏块
系统表空间(SYSTEM、SYSAUX)存储数据字典,坏块影响数据库启动:
• 立即关闭数据库( shutdown abort
,避免进一步损坏);• 从冷备份或RMAN备份恢复系统表空间; • 若备份不完整,需执行不完全恢复(基于SCN或时间点)。
6.2 回滚段坏块
回滚段存储事务回滚信息,坏块导致事务异常:
• 切换至备用回滚段: ALTER SESSION SET rollback_segment = <备用回滚段名>;
;• 重建损坏回滚段:先删除旧回滚段,再创建新回滚段并激活。
6.3 临时段坏块
临时段用于排序、分组等操作,坏块无需修复:
• 临时段会自动重建,重启数据库即可清除坏块; • 若频繁出现,检查临时文件存储介质健康状态。
6.4 索引坏块
索引坏块不影响表数据,直接重建即可:
-- 重建索引(在线重建不影响查询)
ALTER INDEX <索引名> REBUILD ONLINE;
七、坏块问题的高级处理技巧
7.1 BBED工具(底层数据块编辑)
BBED(Block Browser and Editor)是Oracle内部工具,用于直接操作数据块(需谨慎使用):
• 功能:查看数据块结构、修复块头信息、提取坏块中的有效数据; • 风险:操作失误会导致数据永久丢失,需先备份数据文件; • 适用场景:无备份时紧急提取关键数据,或修复块头校验和等简单物理坏块。
7.2 坏块模拟与测试
为验证恢复流程有效性,可人工模拟坏块:
• 用 dd
命令或十六进制编辑器修改数据块内容;• 用Oracle补丁工具(orapatch)篡改块校验和; • 测试RMAN恢复、DBMS_REPAIR等方案的耗时与有效性。
7.3 查找坏块中的具体数据
通过DBMS_ROWID
函数定位坏块对应的行记录:
SELECT rowid, <列名>
FROM <表名>
WHERE DBMS_ROWID.ROWID_TO_ABSOLUTE_FNO(rowid, '<所有者>', '<表名>') = <坏块文件号>
AND DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) = <坏块号>;
八、坏块处理的最佳实践
1. 定期备份是基础:至少保留一份全量冷备份+归档日志,RMAN备份建议每日执行增量备份; 2. 实时监控预警:通过Oracle Enterprise Manager(OEM)或脚本监控告警日志,及时发现坏块; 3. 恢复流程常态化测试:每季度模拟坏块场景,测试恢复方案的可行性; 4. 详细记录处理过程:记录坏块原因、处理步骤、耗时、结果,形成知识库; 5. 坚持预防为主:优先通过参数优化、硬件维护降低坏块发生率,而非依赖事后恢复。
九、总结
Oracle数据库坏块是DBA常见的严重故障,其影响范围从单表查询失败到数据库宕机不等。处理坏块的核心逻辑是:“预防优先,快速定位,分级恢复”——通过定期检查、参数优化避免坏块;通过告警日志和视图快速定位坏块及受影响对象;根据“是否有备份”“对象类型”选择恢复方案(备份恢复优先,无备份时采用跳过/重建策略)。
对于DBA而言,完善的备份策略、熟练的恢复技能、常态化的监控与测试,是最大限度降低坏块损失的关键。记住:任何恢复都无法替代有效的预防。
文中的概念来源于互联网,如有侵权,请联系我删除。
欢迎关注公众号:小周的数据库进阶之路,一起交流AI、数据库、中间件和云计算等技术。如果觉得读完本文有收获,可以转发给其他朋友,大家一起学习进步!感兴趣的朋友可以加我微信,拉您进群与业界的大佬们一起交流学习。




