实战篇:Oracle 数据坏块的 N 种修复方式

简介: 实战篇:Oracle 数据坏块的 N 种修复方式

前言


Oracle 数据库的运行不可避免的会遇到各种各样的错误,就比如数据表出现坏块,此时,你这张表的数据就无法访问了,有什么好的办法可以恢复呢?


什么,你没有遇到过?😱


😏 那就祝你不久的将来遇到,哈哈开个玩笑~ 玩归玩,闹归闹,经验必须要老到!👍🏻


一、介绍


今天就给大家讲讲怎么处理数据表的坏块情况!


对于 Oracle 数据块物理损坏的情形,通常可以分为两种情况:


  • 有备份,通过 RMAN 恢复
  • 无备份,通过 DBMS_REPAIR 修复


1、RMAN

有备份的情况下,这是很理想的情形,我们可以直接通过 RMAN 块介质恢复(BLOCK MEDIA RECOVERY)功能来完成受损块的恢复。


这里我是不建议恢复整个数据库或者数据库文件来修复这些少量受损的数据块,有点浪费时间。


可参考官方文档:Block Media Recovery with RMAN


2、DBMS_REPAIR

那如果没有任何备份怎么办? (PS:备份大于一切!)


我们可以使用 Oracle 自带的 DBMS_REPAIR 包来实现修复。


📢 注意: 使用 DBMS_REPAIR 包来修复,并非完全恢复,而是标记坏块,然后不对起进行访问,这部分被标记的数据也就丢失了,这是无法避免的。


可参考MOS文档:DBMS_REPAIR SCRIPT (Doc ID 556733.1)


二、实战环境准备

1、环境安装

可参考我的一键安装脚本:Oracle 数据库一键安装,从未如此简单

cd /Volumes/DBA/voracle/github/single_db
vagrant up
vagrant ssh

image.png

2、测试数据准备

创建表空间:

create tablespace eason datafile '/oradata/orcl/eason.dbf' size 1g autoextend on;


image.png


创建用户:

create user eason identified by eason default tablespace eason;grant dba to eason;

image.png

创建测试表:

createtable hyj asselect*from dba_objects;

image.png

创建表索引:

create index i_hyj on hyj(object_id);

image.png

3、查看表相关信息

查看表段上的相关信息:

select segment_name , header_file , header_block,blocks from dba_segments where segment_name ='HYJ';

image.png

查出包含行记录的数据块:

selectdistinct dbms_rowid.rowid_block_number(rowid)from eason.hyjorderby1;DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)------------------------------------141114121413        ...
        ...
        ... 
2665266626671232 rows selected.

image.png


📢 注意: 这里看到 HEADER_BLOCK 和 BLOCK_ID 不一致,其实一个 segment 的第一个区的第一个块是 FIRST LEVEL BITMAP BLOCK,第二个块是 SECOND LEVEL BITMAP BLOCK,这两个块是用来管理 free block 的,第三个块是 PAGETABLE SEGMENT HEADER,这个块才是 segment 里的 HEADER_BLOCK。


4、RMAN 备份


首先,我们先做一个全备份,用来演示 RMAN 修复坏块!

run {allocate channel c1 device type disk;allocate channel c2 device type disk;crosscheck backup;crosscheck archivelog all;sql"alter system switch logfile";delete noprompt expired backup;delete noprompt obsolete device type disk;backup database include current controlfile format '/backup/backlv_%d_%T_%t_%s_%p';backup archivelog all DELETE INPUT;release channel c1;release channel c2;}

image.png


5、模拟坏块

破坏 1468、1688、2468 数据块的内容:

dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=1468count=1dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=1688count=1dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=2468count=1

image.png

清除 buffer cache 的内容:

alter system flush buffer_cache;

image.png

再次查询表 hyj,此时查询已经报错,发现有坏块:

select*from eason.hyj;


当然,也可以使用 bbed 进行坏块模拟!


6、坏块检查

下面在介绍几种发现坏块的方式:


1、使用 DBV 检查当前文件的坏块:

dbv file=/oradata/orcl/eason.dbf blocksize=8192;

image.png

使用 DBV检查,同样发现了坏块!


2、使用 rman 检查数据库坏块:

## 检查对应的数据文件
backup check logical validate datafile 5;## 检查当前数据库
backup validate check logical database;

image.png

结合 V$DATABASE_BLOCK_CORRUPTION 视图查看,更加方便:

select*from V$DATABASE_BLOCK_CORRUPTION;

image.png


使用 RMAN 检查后,同样发现了坏块!


3、通过数据库的告警日志也可以发现报错:

image.png


4、通过报错信息快照查找对应的坏表,依次填写数据文件 ID 5 和 坏块 ID 1468:

SELECT tablespace_name, segment_type, owner, segment_name
FROM dba_extents
WHERE file_id =&fileid
and&blockid between block_id AND block_id + blocks -1;

image.png


实验环境准备完毕,下面开始实战!


三、实战演示

今天,我打算使用上述介绍的 2 种方式来演示!


1、RMAN 修复

由于我们之前已经备份了,因此直接使用备份来恢复坏块:

blockrecover datafile 5 block 1468;

image.png

blockrecover datafile 5 block 1688,2468;

image.png

使用同样的方式,依次修复坏块 1688,2468,修复成功后,查询已恢复正常!


再次检查坏块情况:

backup validate check logical database;select*from V$DATABASE_BLOCK_CORRUPTION;

image.png

坏块已经都被恢复,并且数据没有丢失!


2、DBMS_REPAIR 修复

首先,依然使用 dd 先模拟坏块:

dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=3333count=1dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=3368count=1dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=4000count=1

image.png

在没有备份的前提下,我们就无法做到无损修复坏块了,需要损失对应坏块的数据。


1、创建 repair 表,用于记录需要被修复的表:

begindbms_repair.admin_tables(     table_name =>'REPAIR_TABLE',     table_type => dbms_repair.repair_table,     action => dbms_repair.create_action,     tablespace =>'USERS');end;/

image.png


2、创建 Orphan Key 表,用于记录在表块损坏后那些孤立索引,也就是指向坏块的那些索引 :

begindbms_repair.admin_tables(     table_name =>'ORPHAN_KEY_TABLE',     table_type => dbms_repair.orphan_table,     action => dbms_repair.create_action,     tablespace =>'USERS');end;/

image.png

3、检查坏块,检测对象上受损的情形,并返回受损块数为 3:

declare
  num_corrupt int;begin  num_corrupt :=0;DBMS_REPAIR.CHECK_OBJECT(  schema_name =>'EASON',  object_name =>'HYJ',  repair_table_name =>'REPAIR_TABLE',  corrupt_count =>num_corrupt);  dbms_output.put_line('number corrupt:'|| to_char(num_corrupt));end;/

image.png

4、查看受损的块信息:

select object_name, block_id, corrupt_type, marked_corrupt, repair_description from repair_table;


📢 注意: 这里 marked_corrupt 被标记为 TRUE,应该是系统在执行 CHECK_OBJECT 过程中自动完成了FIX_CORRUPT_BLOCKS。如果被标记为 FALSE,需要再运行 FIX_CORRUPT_BLOCKS 来完成坏块的标记工作。


5、修复被损坏的数据块,这些被损坏的数据块是在执行了 check_object 之后生成的:

declare
  cc number;begin  dbms_repair.fix_corrupt_blocks(schema_name =>'EASON',  object_name =>'HYJ',  fix_count => cc);  dbms_output.put_line('Number of blocks fixed: '|| to_char(cc));end;/

image.png

标记了 0 个坏块,说明 CHECK_OBJECT 完成了标记工作。


6、使用 DUMP_ORPHAN_KEYS 过程将那些指向坏块的索引键值填充到 ORPHAN_KEY_TABLE:

declare
   cc number;begin  dbms_repair.dump_orphan_keys(     schema_name =>'EASON',     object_name =>'I_HYJ',     object_type => dbms_repair.index_object,     repair_table_name =>'REPAIR_TABLE',     orphan_table_name=>'ORPHAN_KEY_TABLE',     key_count => cc
);  dbms_output.put_line('Number of orphan keys: '|| to_char(cc));end;/

image.png

表明 202 条记录被损坏丢失!


📢 注意: 此处一定要注意 object_name 是索引名,而不是 table_name,这里 dump 的是损坏的索引信息.如果表有多个索引,需要为每个索引执行 DUMP_ORPHAN_KEYS 操作。


7、验证对象是否可以查询,下面的结果显示依旧无法查询:

selectcount(*)from eason.hyj;

image.png

8、跳过坏块:

BEGIN  DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(     SCHEMA_NAME =>'EASON',     OBJECT_NAME =>'HYJ',     OBJECT_TYPE => dbms_repair.table_object,     FLAGS => dbms_repair.skip_flag);END;/

image.png

📢 注意: 丢失 202 条记录,丢失记录的 rowid 可以在 ORPHAN_KEY_TABLE 表中找到。


9、重建索引:

alter index eason.I_HYJ rebuild;

image.png

10、验证结果

image.png



至此,表中数据可以顺利被访问!


由于坏块并没有消失,而是被标记跳过,因此还是可以查看坏块:

select*from V$DATABASE_BLOCK_CORRUPTION;

image.png

用这种方法可以找回部分数据,也可以找回建了索引的值,但是使用dbv再检查表空间的数据文件时,仍然会显示有损坏的数据块。


这时需要把表的数据全部导出,再重建表或者表空间,然后再把找回的数据导入数据库,推荐用 expdp/impdp 命令做,可以彻底消除 dbv 检查到的坏块。


写在最后


备份大于一切,也是最后的防线,所以请大家一定要做好备份!886


相关文章
|
7天前
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
6天前
|
Oracle 安全 关系型数据库
Oracle数据守卫(DG):数据的“守护者”与“时光机”
【4月更文挑战第19天】Oracle Data Guard保障数据安全,通过实时维护备库实现故障切换,保证业务连续性。它使用日志传输和应用保持数据同步,如同“时光机”,借助闪回技术能恢复误操作数据。此外,它还提供数据压缩、加密和故障转移等功能,提升数据库安全性与性能。作为数据管理员,理解并善用Data Guard是确保企业数据安全的关键。
|
6天前
|
存储 NoSQL Oracle
Oracle 12c的内存列存储:数据的“闪电侠”
【4月更文挑战第19天】Oracle 12c的内存列存储以超高速度革新数据处理,结合列存储与内存技术,实现快速查询与压缩。它支持向量化查询和并行处理,提升效率,但需合理配置以平衡系统资源。作为数据管理员,应善用此功能,适应业务需求和技术发展。
|
6天前
|
存储 Oracle 关系型数据库
Oracle 12c的多重索引:数据的“多维导航仪”
【4月更文挑战第19天】Oracle 12c的多重索引提升数据查询效率,如同多维导航仪。在同一表上创建针对不同列的多个索引,加速检索过程。虽然过多索引会增加存储和维护成本,但合理选择和使用索引策略,结合位图、函数索引等高级特性,能优化查询,应对复杂场景。数据管理员应善用这些工具,根据需求进行索引管理,支持企业数据分析。
|
6天前
|
存储 Oracle 数据管理
Oracle 12c的自动数据优化(ADO)与热图:数据管理的“瘦身”与“透视”艺术
【4月更文挑战第19天】Oracle 12c的ADO和热图技术革新数据管理。ADO智能清理无用数据,优化存储,提升查询速度,实现数据"瘦身";热图则以直观的视觉表示展示数据分布和状态,助力识别性能瓶颈,犹如数据的"透视"工具。这两项技术结合,强化数据管理,为企业业务发展保驾护航。
|
6天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
7天前
|
SQL Oracle 安全
Oracle的PL/SQL循环语句:数据的“旋转木马”与“无限之旅”
【4月更文挑战第19天】Oracle PL/SQL中的循环语句(LOOP、EXIT WHEN、FOR、WHILE)是处理数据的关键工具,用于批量操作、报表生成和复杂业务逻辑。LOOP提供无限循环,可通过EXIT WHEN设定退出条件;FOR循环适用于固定次数迭代,WHILE循环基于条件判断执行。有效使用循环能提高效率,但需注意避免无限循环和优化大数据处理性能。掌握循环语句,将使数据处理更加高效和便捷。
|
7天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL条件控制:数据的“红绿灯”与“分岔路”
【4月更文挑战第19天】在Oracle PL/SQL中,IF语句与CASE语句扮演着数据流程控制的关键角色。IF语句如红绿灯,依据条件决定程序执行路径;ELSE和ELSIF提供多分支逻辑。CASE语句则是分岔路,按表达式值选择执行路径。这些条件控制语句在数据验证、错误处理和业务逻辑中不可或缺,通过巧妙运用能实现高效程序逻辑,保障数据正确流转,支持企业业务发展。理解并熟练掌握这些语句的使用是成为合格数据管理员的重要一环。
|
7天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL表达式:数据的魔法公式
【4月更文挑战第19天】探索Oracle PL/SQL表达式,体验数据的魔法公式。表达式结合常量、变量、运算符和函数,用于数据运算与转换。算术运算符处理数值计算,比较运算符执行数据比较,内置函数如TO_CHAR、ROUND和SUBSTR提供多样化操作。条件表达式如CASE和NULLIF实现灵活逻辑判断。广泛应用于SQL查询和PL/SQL程序,助你驾驭数据,揭示其背后的规律与秘密,成为数据魔法师。
|
7天前
|
运维 Oracle 关系型数据库
Oracle日志文件:数据王国的“记事本”
【4月更文挑战第19天】Oracle日志文件是数据库稳定运行的关键,记录数据变更历史,用于恢复和故障处理。它们协调并发操作,确保数据一致性和完整性。日志文件实时写入操作信息并定期刷新到磁盘,便于数据恢复。然而,日志文件需备份和归档以保证安全性,防止数据丢失。日志文件,数据王国的“记事本”,默默守护数据安全。

推荐镜像

更多