动手实操:Oracle数据库损坏区块的多种修复方法
前言
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
2、测试数据准备
创建表空间:
create tablespace eason datafile '/oradata/orcl/eason.dbf' size 1g autoextend on;
创建用户:
create user eason identified by eason default tablespace eason; grant dba to eason;
创建测试表:
create table hyj as select * from dba_objects;
创建表索引:
create index i_hyj on hyj(object_id);
3、查看表相关信息
查看表段上的相关信息:
select segment_name , header_file , header_block,blocks from dba_segments where segment_name ='HYJ';
查出包含行记录的数据块:
select distinct dbms_rowid.rowid_block_number(rowid) from eason.hyj order by 1; DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) ------------------------------------ 1411 1412 1413 ... ... ... 2665 2666 2667 1232 rows selected.
???? 注意: 这里看到 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; }
5、模拟坏块
破坏 1468、1688、2468 数据块的内容:
dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=1468 count=1 dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=1688 count=1 dd if=/dev/zero of=/oradata/orcl/eason.dbf bs=8192 conv=notrunc seek=2468 count=1
清除 buffer cache 的内容:
alter system flush buffer_cache;
再次查询表 hyj,此时查询已经报错,发现有坏块:
select * from eason.hyj;
当然,也可以使用 bbed 进行坏块模拟!
6、坏块检查
下面在介绍几种发现坏块的方式:
1、使用 DBV 检查当前文件的坏块:
dbv file=/oradata/orcl/eason.dbf blocksize=8192;
使用 DBV检查,同样发现了坏块!
2、使用 rman 检查数据库坏块:
## 检查对应的数据文件 backup check logical validate datafile 5; ## 检查当前数据库 backup validate check logical database;
结合 V$DATABASE_BLOCK_CORRUPTION 视图查看,更加方便:
select * from V$DATABASE_BLOCK_CORRUPTION;