【数据恢复】利用构造ROWID实现无备份情况下绕过ORA-1578、ORA-8103、ORA-1410等逻辑/物理坏块问题
2013-04-28 12:16
627 查看
【数据恢复】利用构造ROWID实现无备份情况下绕过ORA-1578、ORA-8103、ORA-1410等逻辑/物理坏块问题
FROM:http://www.askmaclean.com/archives/build-rowid-workaround-1578-1410-8103.html
2013/04/21 byMaclean
Liu暂无评论
对于无备份情况下的ORA-1578、ORA-8103、ORA-1410等逻辑/物理坏块问题,可以通过如下PL/SQL 构造ROWID的方式挽救绝大多数非坏块的数据, 一般分成 2种情况 有索引可以用来获取ROWID, 或者 没有索引、索引不可用,必须通过dbms_rowid.ROWID_CREATE来构造ROWID的方式。
对于有索引的情况,可以直接使用MOS上提供的脚本:
对于没有索引或者索引损坏的情况可以使用如下方法:
原始脚本如下:
autotrace在绑定变量情况下不准确的问题
11g 新特性IGNORE_ROW_ON_DUPKEY_INDEX提示
数据恢复:模拟2个逻辑坏块
部分行索引使用介绍
数据恢复:解决ORA-600[kghstack_free2][kghstack_err+0068]一例
基于行跟踪的ROWDEPENDENCIES ORA_ROWSCN信息
TRANSACTIONAL
TEXT INDEX全文索引可能消耗大量PGA内存
利用DBMS_ADVISOR.TUNE_MVIEW包生成物化视图创建语句
Goldengate Best Parameters & TEST from Maclean
dbms_stats.lock_table_stats对于没有统计信息的表分区同样有效
FROM:http://www.askmaclean.com/archives/build-rowid-workaround-1578-1410-8103.html
2013/04/21 byMaclean
Liu暂无评论
对于无备份情况下的ORA-1578、ORA-8103、ORA-1410等逻辑/物理坏块问题,可以通过如下PL/SQL 构造ROWID的方式挽救绝大多数非坏块的数据, 一般分成 2种情况 有索引可以用来获取ROWID, 或者 没有索引、索引不可用,必须通过dbms_rowid.ROWID_CREATE来构造ROWID的方式。
对于有索引的情况,可以直接使用MOS上提供的脚本:
REM Create a new table based on the table that is producing errors with no rows: create table as select * from where 1=2; REM Create the table to keep track of ROWIDs pointing to affected rows: create table bad_rows (row_id rowid ,oracle_error_code number); set serveroutput on DECLARE TYPE RowIDTab IS TABLE OF ROWID INDEX BY BINARY_INTEGER; CURSOR c1 IS select /*+ index(tab1) */ rowid from tab1 where is NOT NULL; r RowIDTab; rows NATURAL := 20000; bad_rows number := 0 ; errors number; error_code number; myrowid rowid; BEGIN OPEN c1; LOOP FETCH c1 BULK COLLECT INTO r LIMIT rows; EXIT WHEN r.count=0; BEGIN FORALL i IN r.FIRST..r.LAST SAVE EXCEPTIONS insert into select /*+ ROWID(A) */ from A where rowid = r(i); EXCEPTION when OTHERS then BEGIN errors := SQL%BULK_EXCEPTIONS.COUNT; FOR err1 IN 1..errors LOOP error_code := SQL%BULK_EXCEPTIONS(err1).ERROR_CODE; if error_code in (1410, 8103, 1578) then myrowid := r(SQL%BULK_EXCEPTIONS(err1).ERROR_INDEX); bad_rows := bad_rows + 1; insert into bad_rows values(myrowid, error_code); else raise; end if; END LOOP; END; END; commit; END LOOP; commit; CLOSE c1; dbms_output.put_line('Total Bad Rows: '||bad_rows); END; /
对于没有索引或者索引损坏的情况可以使用如下方法:
创建示例数据 create table maclean_tab1 (t1 int,t2 date default sysdate) tablespace users partition by range(t1) (partition p1 values less than (10000), partition p2 values less than (20000), partition p3 values less than (30000), partition p4 values less than (40000), partition p5 values less than (50000), partition p6 values less than (60000), partition p7 values less than (70000), partition p8 values less than (80000), partition p9 values less than (90000), partition p10 values less than (100000), partition p11 values less than (110000), partition p12 values less than (120000), partition p13 values less than (130000), partition p14 values less than (140000), partition p15 values less than (150000), partition p16 values less than (160000)) ; insert into maclean_tab1(t1) select rownum from dual connect by level<160000; commit; SQL> select count(*) from maclean_tab1; COUNT(*) ---------- 159999 exec dbms_stats.gather_table_stats(USER,'MACLEAN_TAB1'); SQL> alter system flush buffer_cache; System altered. SQL> / System altered. 随即采样一些块来做 坏块 约涉及到10个块的数据 set linesize 200 pagesize 1400 select dbms_rowid.rowid_block_number(rowid) blkid, dbms_rowid.rowid_relative_fno(rowid) rfile from maclean_tab1 sample(0.01) where rownum <= 200 group by dbms_rowid.rowid_block_number(rowid), dbms_rowid.rowid_relative_fno(rowid) order by 1; BLKID RFILE ---------- ---------- 741833 4 741850 4 741994 4 742030 4 742085 4 742141 4 742159 4 742172 4 742173 4 742179 4 制造坏块 [oracle@vrh8 udump]$ rman target / RMAN> blockrecover datafile 4 block 741833,741850,741994,742030,742085,742141,742159,742172,742173,742179 clear; Starting blockrecover at 21-APR-13 using channel ORA_DISK_1 Finished blockrecover at 21-APR-13 SQL> select count(*) from maclean_tab1; select count(*) from maclean_tab1 * ERROR at line 1: ORA-01578: ORACLE data block corrupted (file # 4, block # 741833) ORA-01110: data file 4: '/s01/oradata/G10R25/datafile/o1_mf_users_8nx5srgb_.dbf' 通过blockrecover datafile block clear 构造了一系列坏块且没有备份 ,我们通过下列脚本挽回大部分可用数据 一个实际操作过程 drop table maclean_tab_backup; create table maclean_tab_backup tablespace users nologging compress pctfree 0 pctused 99 --可以注释掉的 as select * from maclean_tab1 where 1=0; drop table bad_rows; create table bad_rows (row_id rowid,oracle_error_code varchar2(50)) tablespace users nologging compress pctfree 0 pctused 99 --可以注释掉的; set serveroutput on; set timing on; DECLARE TYPE RowIDTab IS TABLE OF ROWID INDEX BY BINARY_INTEGER; CURSOR Crowid_info IS select Do.DATA_OBJECT_ID dataid, DE.FILE_ID fid, DE.BLOCK_ID blkid, DE.BLOCKS blkcnt from dba_objects DO, dba_extents DE where DO.OBJECT_NAME = 'MACLEAN_TAB1' --and DE.PARTITION_NAME='&PARTITION_NAME' --若指定分区则取消注释 and nvl(DO.SUBOBJECT_NAME,'-1') = nvl(DE.PARTITION_NAME,'-1') and DO.OBJECT_NAME = DE.SEGMENT_NAME and DO.owner = 'SYS' order by 1, 2, 3 asc; bad_rows number := 0; errors varchar2(500); error_code varchar2(500); myrowid rowid; BEGIN /* Maclean Liu http://www.askmaclean.com * Copy Right 2013-4-20 */ execute immediate 'alter session set commit_write=''batch,nowait'' '; for i in Crowid_info loop for j in 0 .. i.blkcnt - 1 loop for z in 0 .. 2000 loop begin myrowid := dbms_rowid.ROWID_CREATE(1, i.dataid, i.fid, i.blkid + j, z); insert into maclean_tab_backup select /*+ ROWID(A) */ * from maclean_tab1 A where rowid = myrowid; EXCEPTION when OTHERS then BEGIN errors := SQLERRM; error_code := SQLCODE; if (error_code like '%1410%' or error_code like '%8103%' or error_code like '%1578%') then bad_rows := bad_rows + 1; insert into bad_rows values (myrowid, error_code); commit; else raise; end if; END; commit; end; end loop; end loop; end loop; dbms_output.put_line('Total Bad Rows: ' || bad_rows); commit; END; / Elapsed: 00:01:10.16 SQL> select count(*) from maclean_tab_backup; COUNT(*) ---------- 155921 ===>损失了少量的10个块的数据
原始脚本如下:
步骤1 创建备份表 create table <new table name> as select * from <original table name> where 1=2; 步骤2 创建bad_rows表 create table bad_rows (row_id rowid,oracle_error_code varchar2(50)); 步骤3 运行下列脚本 DECLARE TYPE RowIDTab IS TABLE OF ROWID INDEX BY BINARY_INTEGER; CURSOR Crowid_info IS select Do.DATA_OBJECT_ID dataid, DE.FILE_ID fid, DE.BLOCK_ID blkid, DE.BLOCKS blkcnt from dba_objects DO, dba_extents DE where DO.OBJECT_NAME = '&TABNAME' --and DE.PARTITION_NAME='&PARTITION_NAME' --若指定分区则取消注释 and nvl(DO.SUBOBJECT_NAME,'-1') = nvl(DE.PARTITION_NAME,'-1') and DO.OBJECT_NAME = DE.SEGMENT_NAME and DO.owner = '&OWNER' order by 1, 2, 3 asc; bad_rows number := 0; errors varchar2(500); error_code varchar2(500); myrowid rowid; BEGIN /* Maclean Liu http://www.askmaclean.com * Copy Right 2013-4-20 */ execute immediate 'alter session set commit_write=''batch,nowait'' '; for i in Crowid_info loop for j in 0 .. i.blkcnt - 1 loop for z in 0 .. 2000 loop begin myrowid := dbms_rowid.ROWID_CREATE(1, i.dataid, i.fid, i.blkid + j, z); insert into &backup_table select /*+ ROWID(A) */ * from &source_table A where rowid = myrowid; EXCEPTION when OTHERS then BEGIN errors := SQLERRM; error_code := SQLCODE; if (error_code like '%1410%' or error_code like '%8103%' or error_code like '%1578%') then bad_rows := bad_rows + 1; insert into bad_rows values (myrowid, error_code); commit; else raise; end if; END; commit; end; end loop; end loop; end loop; dbms_output.put_line('Total Bad Rows: ' || bad_rows); commit; END; /
构造ROWID绕过ORA-1578、ORA-8103、ORA-1410脚本下载
相关文章 | Related posts:autotrace在绑定变量情况下不准确的问题
11g 新特性IGNORE_ROW_ON_DUPKEY_INDEX提示
数据恢复:模拟2个逻辑坏块
部分行索引使用介绍
数据恢复:解决ORA-600[kghstack_free2][kghstack_err+0068]一例
基于行跟踪的ROWDEPENDENCIES ORA_ROWSCN信息
TRANSACTIONAL
TEXT INDEX全文索引可能消耗大量PGA内存
利用DBMS_ADVISOR.TUNE_MVIEW包生成物化视图创建语句
Goldengate Best Parameters & TEST from Maclean
dbms_stats.lock_table_stats对于没有统计信息的表分区同样有效
相关文章推荐
- 【数据恢复】利用构造ROWID实现无备份情况下绕过ORA-1578、ORA-8103、ORA-1410等逻辑/物理坏块问题
- SQL Server利用日志备份恢复数据到时间点的问题
- MS SQL Server利用日志备份恢复数据到时间点的问题
- 数据文件被误删,解决ORA-376,ORA-1578,ORA-8103问题
- Mysql的数据备份类型——物理备份与逻辑备份,全量与增量
- 利用rsync实现数据远程容灾备份
- 利用ftp命令+bat程序实现本地数据定时备份到服务器
- java代码实现数据的备份和恢复
- Oracle 之利用BBED修改数据块SCN----没有备份数据文件的数据恢复
- 利用DataGridView及Excel实现数据的导入导出备份
- 利用javascript实现可视化数据备份[原创]
- MSSQL · 最佳实践 · 利用文件组实现冷热数据隔离备份方案
- 偷梁换柱 | 无备份情况下的数据恢复实践
- 【Docker】利用数据卷容器来备份、恢复、迁移数据卷
- 数据恢复:模拟2个逻辑坏块
- ORA-03113: 通信通道的文件结尾以及用备份的数据文件恢复原数据库的解决方案
- java实现数据库备份和恢复源码---解决路径带空格引发的问题
- App开发如何利用Fidder,在api接口还没有实现的情况下模拟数据,继续开发
- iOS实战演练之关于数据交互的问题(利用XAMPP搭建本地服务器, 编写PHP代码实现iOS端注册登录功能)
- 利用rsync实现金笛邮件的用户数据的增量备份