如果自己搞不定可以找诗檀软件专业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