Oracle DBMS_REPAIR 示例

 

如果自己搞不定可以找诗檀软件专业ORACLE数据库修复团队成员帮您恢复!

诗檀软件专业数据库修复团队

服务热线 : 13764045638 QQ号:47079569 邮箱:service@parnassusdata.com

 

 
目的
本文献提供了DBMS_REPAIR(在 Oracle 8i引入)的例子。 Oracle提供了多种不同的检测和修正数据块损坏的方法,DBMS_REPAIR就是其中之一。
警告: 涉及数据丢失的任何损坏,需要分析、了解这些数据是如何融入整个数据库系统,根据维修的性质,可能会丢失数据,导致逻辑的不一致,所以,需要仔细权衡使用DBMS_REPAIR.的利弊。

范围和应用
本文仅仅旨在帮助有经验的数据库管理员与Oracle全球支持分析师的工作,本文不包含有关DBMS_REPAIR包的一般信息,相反,它旨在提供可以由用户(借助Oracle技术支持分析师的协助)进行定制的示例代码来解决数据库损坏问题。应阅读Oracle数据库管理员指南的“检测并修复数据块损坏”一章,在开始之前进行风险评估分析。
相关文献
Oracle 数据库管理员指南, DBMS_REPAIR章节
引言
=============

注释: DBMS_REPAIR 包仅用于同处理层和数据层的损坏(软件损坏快)一起工作。发生物理损坏的块被标记(例如:断裂块),因为该块被写入高速缓存缓冲区,DBMS_REPAIR忽略了所有标记为损坏的块。
DBMS_REPAIR的最初版本的唯一的块修复是
*** 标记块软件损坏 ***.

使用包之前,应进行损坏文件的备份。

数据库摘要
===============

损坏的块存在于表T1中

SQL> desc t1
Name Null? Type
—————————————– ——– —————————-
COL1 NOT NULL NUMBER(38)
COL2 CHAR(512)
SQL> 分析表 t1 验证结构;
分析表 t1 验证结构*
ERROR at line 1:
ORA-01498: 块检查失败 – 见跟踪文件
—> 注释: 在从ANALYZE产生的跟踪文件中,可以判断损坏的块包含3行数据(nrows = 3).
— 跟踪文件的主导线如下:
Dump file /export/home/oracle/product/8.1.5/admin/V815/udump/v815_ora_2835.trc
Oracle8 Enterprise Edition Release 8.1.5.0.0 – Beta
With the Partitioning option

*** 1998.12.16.15.53.02.000
*** SESSION ID:(7.6) 1998.12.16.15.53.02.000
kdbchk: row locked by non-existent transaction
table=0 slot=0
lockid=32 ktbbhitc=1
Block header dump: 0x01800003
Object id on Block? Y
seg/obj: 0xb6d csc: 0x00.1cf5f itc: 1 flg: – typ: 1 – DATA
fsl: 0 fnx: 0x0 ver: 0x01

Itl Xid Uba Flag Lck Scn/Fsc
0x01 xid: 0x0002.011.00000121 uba: 0x008018fb.0345.0d –U- 3 fsc
0x0000.0001cf60

data_block_dump
===============
tsiz: 0x7b8
hsiz: 0x18
pbl: 0x28088044
bdba: 0x01800003
flag=———–
ntab=1
nrow=3
frre=-1
fsbo=0x18
fseo=0x19d
avsp=0x185
tosp=0x185
0xe:pti[0] nrow=3 offs=0
0x12:pri[0] offs=0x5ff
0x14:pri[1] offs=0x3a6
0x16:pri[2] offs=0x19d
block_row_dump:

[… 不包括文件的剩余部分]

end_of_block_dump
DBMS_REPAIR.ADMIN_TABLES (修复和孤立键
================================================

ADMIN_TABLES 提供了管理修复和孤立键表的功能

SQL> @adminCreate
SQL> connect sys/change_on_install
Connected.
SQL>
SQL> — Repair Table
SQL>
SQL> declare
2 begin
3 — Create repair table
4 dbms_repair.admin_tables (
5 — table_name => ‘REPAIR_TABLE’,
6 table_type => dbms_repair.repair_table,
7 action => dbms_repair.create_action,
8 tablespace => ‘USERS’); — default TS of SYS if not specified
9 end;
10 /

PL/SQL 程序成功完成.

SQL> select owner, object_name, object_type
2 from dba_objects
3 where object_name like ‘%REPAIR_TABLE’;

OWNER OBJECT_NAME OBJECT_TYPE
——————————————————————
SYS DBA_REPAIR_TABLE VIEW
SYS REPAIR_TABLE TABLE
SQL>
SQL> — Orphan Key Table
SQL>
SQL> declare
2 begin
3 — Create orphan key table
4 dbms_repair.admin_tables (
5 table_type => dbms_repair.orphan_table,
6 action => dbms_repair.create_action,
7 tablespace => ‘USERS’); — default TS of SYS if not specified
8 end;
9 /

PL/SQL 程序成功完成
SQL> select owner, object_name, object_type
2 from dba_objects
3 where object_name like ‘%ORPHAN_KEY_TABLE’;

OWNER OBJECT_NAME OBJECT_TYPE
——————————————————————
SYS DBA_ORPHAN_KEY_TABLE VIEW
SYS ORPHAN_KEY_TABLE TABLE
DBMS_REPAIR.CHECK_OBJECT
=========================

CHECK_OBJECT 程序检查指定的对象,并且,用有关损坏和修复指令的信息填充修复的表,验证包括对对象中的所有的块进行检查,会跳过所有之前被标记为损坏的块。

注释: 在DBMS_REPAIR 的初始版本中,唯一的修复是将块标记为软件损坏。

SQL> @checkObject
SQL> set serveroutput on
SQL>
SQL> declare
2 rpr_count int;
3 begin
4 rpr_count := 0;
5 dbms_repair.check_object (
6 schema_name => ‘SYSTEM’,
7 object_name => ‘T1’,
8 repair_table_name => ‘REPAIR_TABLE’,
9 corrupt_count => rpr_count);
10 dbms_output.put_line(‘repair count: ‘ || to_char(rpr_count));
11 end;
12 /
repair count: 1

PL/SQL 程序成功完成

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

SQL> select object_name, block_id, corrupt_type, marked_corrupt,
2 corrupt_description, repair_description
3 from repair_table;

OBJECT_NAME BLOCK_ID CORRUPT_TYPE MARKED_COR
—————————— ———- ———— ———-
CORRUPT_DESCRIPTION
——————————————————————————–
REPAIR_DESCRIPTION
——————————————————————————–
T1 3 1 FALSE
kdbchk: row locked by non-existent transaction
table=0 slot=0
lockid=32 ktbbhitc=1
mark block software corrupt
数据提取
===============

修复表表明文件6的块3已损坏,但是,该块目前还没有被标记为损坏,所以,现在正是提取任何有意义的数据的时候,当块被标记为损坏之后,必须跳过整个块。
1. 确定 ALTER SYSTEM DUMP块中的行数 (nrows = 3).
2. 使用块转储,观察是否可以保存一些数据.

DBMS_REPAIR.FIX_CORRUPT_BLOCKS (ORA-1578)
============================================

记忆修复表的信息,FIX_CORRUPT_BLOCKS 程序修复指定对象中损坏的块,块被标记为损坏之后,当执行全表扫描之后,ORA-1578 显示结果。
SQL> declare
2 fix_count int;
3 begin
4 fix_count := 0;
5 dbms_repair.fix_corrupt_blocks (
6 schema_name => ‘SYSTEM’,
7 object_name => ‘T1’,
8 object_type => dbms_repair.table_object,
9 repair_table_name => ‘REPAIR_TABLE’,
10 fix_count => fix_count);
11 dbms_output.put_line(‘fix count: ‘ || to_char(fix_count));
12 end;
13 /
fix count: 1

PL/SQL 程序成功完成.

SQL> select object_name, block_id, marked_corrupt
2 from repair_table;

OBJECT_NAME BLOCK_ID MARKED_COR
—————————— ———- ———-
T1 3 TRUE

SQL> select * from system.t1;
select * from system.t1
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 3)
ORA-01110: data file 6: ‘/tmp/ts_corrupt.dbf’
DBMS_REPAIR.DUMP_ORPHAN_KEYS
==============================

DUMP_ORPHAN_KEYS 显示指向损坏数据块的行的索引条目。

SQL> select index_name from dba_indexes
2 where table_name in (select distinct object_name from repair_table);

INDEX_NAME
——————————
T1_PK

SQL> @dumpOrphanKeys
SQL> set serveroutput on
SQL>
SQL> declare
2 key_count int;
3 begin
4 key_count := 0;
5 dbms_repair.dump_orphan_keys (
6 schema_name => ‘SYSTEM’,
7 object_name => ‘T1_PK’,
8 object_type => dbms_repair.index_object,
9 repair_table_name => ‘REPAIR_TABLE’,
10 orphan_table_name => ‘ORPHAN_KEY_TABLE’,
11 key_count => key_count);
12 dbms_output.put_line(‘orphan key count: ‘ || to_char(key_count));
13 end;
14 /
orphan key count: 3
PL/SQL 程序成功完成.

SQL> 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

SQL> select index_name, count(*) from orphan_key_table
2 group by index_name;

INDEX_NAME COUNT(*)
—————————— ———-
T1_PK 3

注释:孤立的键表中的索引条目意味着该指数应重建,以保证表探头和索引探头返回相同的结果集。
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS
===============================

SKIP_CORRUPT_BLOCKS 允许/禁止对指定对象的索引和表扫描时数据块的跳跃。

注释: 如果索引和表不同步,那么,只读SET TRANSACTION,在一个查询探头只有索引,然后后续查询探头既有索引又有表时,进程可能不一致,如果表块被标记为损坏,那么两个查询将会返回不同的结果。

建议: SKIP_CORRUPT_BLOCKS 被启用,那么重建孤立的键表确认的所有索引(或者,如果DUMP_ORPHAN_KEYS 被省略,则重建与对象相关的所有索引)。

SQL> @skipCorruptBlocks
SQL> declare
2 begin
3 dbms_repair.skip_corrupt_blocks (
4 schema_name => ‘SYSTEM’,
5 object_name => ‘T1’,
6 object_type => dbms_repair.table_object,
7 flags => dbms_repair.skip_flag);
8 end;
9 /

PL/SQL 程序成功完成
SQL> select table_name, skip_corrupt from dba_tables
2 where table_name = ‘T1’;

TABLE_NAME SKIP_COR
—————————— ——–
T1 ENABLED

SQL> — rows in corrupt block skipped, no errors on full table scan
SQL> select * from system.t1;

COL1 COL2
——————————————————————————–
4 dddd
5 eeee

–> Notice the pk index has not yet been corrected.

SQL> insert into system.t1 values (1,’aaaa’);
insert into system.t1 values (1,’aaaa’)
*
SQL> select * from system.t1 where col1 = 1;

no rows selected
DBMS_REPAIR.REBUILD_FREELISTS
===============================

REBUILD_FREELISTS 为指定对象重建自由表。
SQL> declare
2 begin
3 dbms_repair.rebuild_freelists (
4 schema_name => ‘SYSTEM’,
5 object_name => ‘T1’,
6 object_type => dbms_repair.table_object);
7 end;
8 /

PL/SQL 程序成功完成

重建索引
=============

注释: 应该重建孤立的键表确认的每个索引以保证结果的一致性。

SQL> alter index system.t1_pk rebuild online;

Index altered.

SQL> insert into system.t1 values (1, ‘aaaa’);

1 row created.

SQL> select * from system.t1;

COL1 COL2
——————————————————————————–
4 dddd
5 eeee
1 aaaa

注释 – 上面插入的语句是一个简单的例子,这是一个完美的世界,我们知道丢失的数据。临时表(temp_t1) 也应该包括从损坏的块中提取的所有的行。
结论
==========
在这一点上表T1可用,但是导致了数据丢失,通常,使用DBMS_REPAIR包之前必须严肃地考虑数据丢失问题,因为,挖掘索引块和/或表块转储很复杂,可能会引起逻辑不一致问题的出现。在最初的版本中,受DBMS_REPAIR影响的唯一的修复是将块标记为软件损坏。

参考文献
============
Note:556733.1 DBMS_REPAIR SCRIPT

<
参考文献

NOTE:556733.1 – DBMS_REPAIR SCRIPT
NOTE:1088018.1 – Master Note for Handling Oracle Database Corruption Issues

关注刘相兵的新浪微博

扫码加入微信Oracle小密圈,了解Oracle最新技术下载分享资源

Speak Your Mind

沪公网安备 31010802001379号

TEL/電話+86 13764045638
Email service@parnassusdata.com
QQ 47079569