Oracle 数据库坏块处理

 

情形一,有RMAN备份


1.构造坏块


SQL> select segment_name , header_file , header_block,blocks
2 from dba_segments where segment_name =‘TESTC‘ and owner=‘SCOTT‘;

SEGMENT_NA HEADER_FILE HEADER_BLOCK BLOCKS
---------- ----------- ------------ ----------
TESTC          4            154         8


[oracle@prim scripts]$ dd of=/oradata/orcl/users01.dbf bs=8192 conv=notrunc seek=155 <<EOF
> Corrupt me!
> EOF

dd of=/oradata/orcl/users01.dbf bs=8192 conv=notrunc seek=157 <<EOF
Corrupt me!
0+1 records in
0+1 records out
12 bytes (12 B) copied, 0.0145481 s, 0.8 kB/s
[oracle@prim scripts]$
[oracle@prim scripts]$ dd of=/oradata/orcl/users01.dbf bs=8192 conv=notrunc seek=157 <<EOF
> Corrupt me!
> EOF
0+1 records in
0+1 records out
12 bytes (12 B) copied, 0.00138089 s, 8.7 kB/s
[oracle@prim scripts]$
[oracle@prim scripts]$
[oracle@prim scripts]$ dd of=/oradata/orcl/users01.dbf bs=8192 conv=notrunc seek=159 <<EOF
> Corrupt me!
> EOF
0+1 records in
0+1 records out
12 bytes (12 B) copied, 0.00227023 s, 5.3 kB/s


2.查询有坏块的表
SQL> select * from scott.TESTC;
select * from scott.TESTC
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 155)
ORA-01110: data file 4: ‘/oradata/orcl/users01.dbf‘


3.RMAN 利用 DRA 修复坏块

[oracle@prim scripts]$ rman target /

Recovery Manager: Release 11.2.0.4.0 - Production on Thu Jul 2 11:21:04 2020

Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

connected to target database: ORCL (DBID=1570665551)

RMAN> validate datafile 4;

Starting validate at 02-JUL-20
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=24 device type=DISK
allocated channel: ORA_DISK_2
channel ORA_DISK_2: SID=400 device type=DISK
allocated channel: ORA_DISK_3
channel ORA_DISK_3: SID=25 device type=DISK
allocated channel: ORA_DISK_4
channel ORA_DISK_4: SID=405 device type=DISK
channel ORA_DISK_1: starting validation of datafile
channel ORA_DISK_1: specifying datafile(s) for validation
input datafile file number=00004 name=/oradata/orcl/users01.dbf
channel ORA_DISK_1: validation complete, elapsed time: 00:00:07
List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
4 FAILED 0 37031 46597 2127979
File Name: /oradata/orcl/users01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 5819
Index 0 912
Other 3 2798

validate found one or more corrupt blocks
See trace file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_27968.trc for details
Finished validate at 02-JUL-20

RMAN> list failure;

List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------- -------
622 HIGH OPEN 02-JUL-20 Datafile 4: ‘/oradata/orcl/users01.dbf‘ contains one or more corrupt blocks


RMAN> advise failure;

List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------- -------
622 HIGH OPEN 02-JUL-20 Datafile 4: ‘/oradata/orcl/users01.dbf‘ contains one or more corrupt blocks

analyzing automatic repair options; this may take some time
using channel ORA_DISK_1
using channel ORA_DISK_2
using channel ORA_DISK_3
using channel ORA_DISK_4
analyzing automatic repair options complete

Mandatory Manual Actions
========================
no manual actions available

Optional Manual Actions
=======================
1. Shut down, mount the database and try flush redo using ALTER SYSTEM FLUSH REDO TO ‘standby name‘ command. Then perform a Data Guard role change (failover). Available standbys: orcl_std.

Automated Repair Options
========================
Option Repair Description
------ ------------------
1 Recover multiple corrupt blocks in datafile 4
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_2285196485.hm

RMAN> repair failure;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_2285196485.hm

contents of repair script:
# block media recovery for multiple blocks
recover datafile 4 block 155, 157, 159;

Do you really want to execute the above repair (enter YES or NO)? yes
executing repair script

Starting recover at 02-JUL-20
using channel ORA_DISK_1
using channel ORA_DISK_2
using channel ORA_DISK_3
using channel ORA_DISK_4
searching flashback logs for block images until SCN 2123598
finished flashback log search, restored 3 blocks

starting media recovery
media recovery complete, elapsed time: 00:00:01

Finished recover at 02-JUL-20
repair failure complete

4.验证坏块修复后的结果:

RMAN> validate datafile 4;

Starting validate at 02-JUL-20
using channel ORA_DISK_1
using channel ORA_DISK_2
using channel ORA_DISK_3
using channel ORA_DISK_4
channel ORA_DISK_1: starting validation of datafile
channel ORA_DISK_1: specifying datafile(s) for validation
input datafile file number=00004 name=/oradata/orcl/users01.dbf
channel ORA_DISK_1: validation complete, elapsed time: 00:00:01
List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
4 OK 0 37031 46597 2128902
File Name: /oradata/orcl/users01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data        0        5822
Index        0        912
Other        0        2795

Finished validate at 02-JUL-20

 

情形二,无任何备份

 

使用 DBMS_REPAIR 修复(跳过)坏块
 
 
create table testc(
col1 number primary key,
col2 varchar2(20),
col3 number(11));
 
insert into testc values(1,‘AAAAAA‘,13012345678);
insert into testc values(2,‘BBBBBB‘,13112345678);
insert into testc values(3,‘CCCCCC‘,13212345678);
 
 
 
 
col SEGMENT_NAME for a10
select segment_name , header_file , header_block,blocks
from dba_segments where segment_name =‘TESTC‘ and owner=‘SCOTT‘;
 
SEGMENT_NA HEADER_FILE HEADER_BLOCK     BLOCKS
---------- ----------- ------------ ----------
TESTC                4          154          8
 
dd of=/oradata/orcl/users01.dbf bs=8192 conv=notrunc seek=155 <<EOF
Corrupt me!
EOF
 
dd of=/oradata/orcl/users01.dbf bs=8192 conv=notrunc seek=157 <<EOF
Corrupt me!
EOF
 
 
dd of=/oradata/orcl/users01.dbf bs=8192 conv=notrunc seek=159 <<EOF
Corrupt me!
EOF
 
alter system flush buffer_cache;
 
 
select * from scott.TESTC;
 
SQL> select * from scott.TESTC;
select * from scott.TESTC
                    *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 155)
ORA-01110: data file 4: ‘/oradata/orcl/users01.dbf‘
 
 
4、使用DBMS_REPAIR修复坏块
 
 
step a 创建修复表对象
 
drop table REPAIR_TABLE purge;
begin
-- Create repair table
dbms_repair.admin_tables (
table_name => ‘REPAIR_TABLE‘,
table_type => dbms_repair.repair_table,
action => dbms_repair.create_action,
tablespace => ‘USERS‘);
end;
/
 
select owner, object_name, object_type
from dba_objects
where object_name like ‘%REPAIR_TABLE‘;
 
OWNER    OBJECT_NAME          OBJECT_TYPE
-------- -------------------- --------------------
SYS      DBA_REPAIR_TABLE     VIEW
SYS      REPAIR_TABLE         TABLE
 
 
--使用DBMS_REPAIR.ADMIN_TABLES过程创建一个表对象,用于记录在表块损坏后那些孤立索引,也就是指向坏块的那些索引
 
-- Orphan Key Table
 
drop table ORPHAN_KEY_TABLE purge;
 
begin
-- Create orphan key table
dbms_repair.admin_tables (
table_type => dbms_repair.orphan_table,
action => dbms_repair.create_action,
tablespace => ‘USERS‘); -- default TS of SYS if not specified
end;
/
 
col OBJECT_NAME for a30
col OBJECT_TYPE for a25
select owner, object_name, object_type
from dba_objects
where object_name like ‘%ORPHAN_KEY_TABLE‘;
 
OWNER      OBJECT_NAME          OBJECT_TYPE
---------- -------------------- --------------------
SYS        ORPHAN_KEY_TABLE     TABLE
SYS        DBA_ORPHAN_KEY_TABLE VIEW
 
 
Step b 校验受损的对象
--使用DBMS_REPAIR.CHECK_OBJECT来检测对象上受损的情形,并返回受损块数
 
set serveroutput on
declare
rpr_count int;
begin
rpr_count := 0;
dbms_repair.check_object (
schema_name => ‘SCOTT‘,
object_name => ‘TESTC‘,
repair_table_name => ‘REPAIR_TABLE‘,
corrupt_count => rpr_count);
dbms_output.put_line(‘repair count: ‘ || to_char(rpr_count));
end;
/
 
repair count: 3
 
--下面我们可以从repair_table查询到受损的块
--从下面的查询中可以看出列marked_corrupt全部为true,表明我们在CHECK_OBJECT已经标注了坏块
 
SQL> desc repair_table
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
OBJECT_ID                                 NOT NULL NUMBER
TABLESPACE_ID                             NOT NULL NUMBER
RELATIVE_FILE_ID                          NOT NULL NUMBER
BLOCK_ID                                  NOT NULL NUMBER
CORRUPT_TYPE                              NOT NULL NUMBER
SCHEMA_NAME                               NOT NULL VARCHAR2(30)
OBJECT_NAME                               NOT NULL VARCHAR2(30)
BASEOBJECT_NAME                                    VARCHAR2(30)
PARTITION_NAME                                     VARCHAR2(30)
CORRUPT_DESCRIPTION                                VARCHAR2(2000)
REPAIR_DESCRIPTION                                 VARCHAR2(200)
MARKED_CORRUPT                            NOT NULL VARCHAR2(10)
CHECK_TIMESTAMP                           NOT NULL DATE
FIX_TIMESTAMP                                      DATE
REFORMAT_TIMESTAMP                                 DATE
set lines 120
col OBJECT_NAME for a12
col REPAIR_DESCRIPTION for a30
col CORRUPT_DESCRIPTION for a25
select object_name, block_id, corrupt_type, marked_corrupt,
corrupt_description, repair_description
from repair_table;
OBJECT_NAME    BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DESCRIPTION       REPAIR_DESCRIPTION
------------ ---------- ------------ ---------- ------------------------- ------------------------------
TESTC               155         6148 TRUE                                 mark block software corrupt
TESTC               157         6148 TRUE                                 mark block software corrupt
TESTC               159         6148 TRUE                                 mark block software corrupt
 
 
Step c 标记坏块
--过程FIX_CORRUPT_BLOCKS用于标记坏块,在这个演示中,我们在CHECK_OBJECT已经被标注了,如没有执行下面的过程
--由于上一步已经标注,所以下面的输出为0
 
 
SET SERVEROUTPUT ON
declare
fix_count int;
begin
fix_count := 0;
dbms_repair.fix_corrupt_blocks (
schema_name => ‘SCOTT‘,
object_name => ‘TESTC‘,
object_type => dbms_repair.table_object,
repair_table_name => ‘REPAIR_TABLE‘,
fix_count => fix_count);
dbms_output.put_line(‘fix count: ‘ || to_char(fix_count));
end;
/
 
num fix: 0
 
 
 
select object_name, block_id, marked_corrupt from repair_table;
 
OBJECT_NAME    BLOCK_ID MARKED_COR
------------ ---------- ----------
TESTC               155 TRUE
TESTC               157 TRUE
TESTC               159 TRUE
 
 
select * from scott.TESTC;
 
select * from scott.TESTC
                    *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 147)
ORA-01110: data file 4: ‘/oradata/orcl/users01.dbf‘
 
 
 
DBMS_REPAIR.DUMP_ORPHAN_KEYS
==============================
 
DUMP_ORPHAN_KEYS reports on index entries that point to rows in corrupt data blocks.
 
SQL> select index_name from dba_indexes where table_name in (select distinct object_name from repair_table);
 
INDEX_NAME
------------------------------
SYS_C0011945
 
 
 
 
 
Step d DUMP孤立的索引键值
--使用DUMP_ORPHAN_KEYS过程将那些指向坏块的索引键值填充到ORPHAN_KEY_TABLE
 
 
set serveroutput on
declare
key_count int;
begin
key_count := 0;
dbms_repair.dump_orphan_keys (
schema_name => ‘SCOTT‘,
object_name => ‘SYS_C0011945‘,
object_type => dbms_repair.index_object,
repair_table_name => ‘REPAIR_TABLE‘,
orphan_table_name => ‘ORPHAN_KEY_TABLE‘,
key_count => key_count);
dbms_output.put_line(‘orphan key count: ‘ || to_char(key_count));
end;
/
 
orphan key count: 3
 
 
 
 
desc orphan_key_table
Name                      Null?    Type
------------------------- -------- ----------------------------
SCHEMA_NAME               NOT NULL VARCHAR2(30)
INDEX_NAME                NOT NULL VARCHAR2(30)
IPART_NAME                         VARCHAR2(30)
INDEX_ID                  NOT NULL NUMBER
TABLE_NAME                NOT NULL VARCHAR2(30)
PART_NAME                          VARCHAR2(30)
TABLE_ID                  NOT NULL NUMBER
KEYROWID                  NOT NULL ROWID
KEY                       NOT NULL ROWID
DUMP_TIMESTAMP            NOT NULL DATE
 
 
select index_name, count(*) from orphan_key_table group by index_name;
 
INDEX_NAME                       COUNT(*)
------------------------------ ----------
SYS_C0011945                            3
 
 
 
 
Step e 跳过坏块
 
--使用SKIP_CORRUPT_BLOCKS来告知Oracle哪些坏块需要被跳过
begin
dbms_repair.skip_corrupt_blocks (
schema_name => ‘SCOTT‘,
object_name => ‘TESTC‘,
object_type => dbms_repair.table_object,
flags => dbms_repair.skip_flag);
end;
/
 
select table_name, skip_corrupt from dba_tables where table_name = ‘TESTC‘;
 
TABLE_NAME                     SKIP_COR
------------------------------ --------
TESTC                            ENABLED
 
 
SQL> select * from scott.TESTC;
 
no rows selected  
 
 
SQL> insert into scott.testc values (1,‘aaaaaa‘,13111111111);
insert into scott.testc values (1,‘aaaaaa‘,13111111111)
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.SYS_C0011945) violated
 
 
 
SQL> select * from scott.testc where col1=1;
 
no rows selected
 
   
REBUILD_FREELISTS rebuilds freelists for the specified object.      
 
begin
dbms_repair.rebuild_freelists (
schema_name => ‘SCOTT‘,
object_name => ‘TESTC‘,
object_type => dbms_repair.table_object);
end;
/    
---此操作报错
 
begin
*
ERROR at line 1:
ORA-10614: Operation not allowed on this segment
ORA-06512: at "SYS.DBMS_REPAIR", line 401
ORA-06512: at line 2
 
 
--由于索引键上存在孤立索引,因此我们重建索引:
 
alter index scott.SYS_C0011945 rebuild online;
 
 
再次插入数据,没有了主键冲突
 
SQL> insert into scott.testc values (1,‘aaaaaa‘,13111111111);
 
1 row created.
 
SQL> commit ;
 
Commit complete.
 
 
SQL> select * from scott.testc ;
 
      COL1 COL2                       COL3
---------- -------------------- ----------
         1 aaaaaa               1.3111E+10

Oracle 数据库坏块处理

上一篇:初学Delphi,如何用delphi编写ini文件设置SQL数据库的连接!急!(100分)


下一篇:Mysql 跨库数据迁移 -- python 脚本