创建测试表: SQL> drop table testtest; Table dropped. SQL> create table testtest as select * from dba_objects; Table created. SQL> create index i_test on testtest(object_id); Index created. SQL> col SEGMENT_NAME format a15 SQL> SQL> SQL> select segment_name , header_file , header_block,blocks from dba_segments where segment_name ='TESTTEST'; SEGMENT_NAME HEADER_FILE HEADER_BLOCK BLOCKS --------------- ----------- ------------ ---------- TESTTEST 201 1938 1536 select * from dba_extents where segment_name='TESTTEST' and owner='TT'; 制造测试数据(坏块) dd if=/dev/zero of=/u02/app/oracle/oradata/TEST/datafile/o1_mf_tt_m7kvq4fy_.dbf bs=8192 conv=notrunc seek=2180 count=1 dd if=/dev/zero of=/u02/app/oracle/oradata/TEST/datafile/o1_mf_tt_m7kvq4fy_.dbf bs=8192 conv=notrunc seek=2310 count=1 dd if=/dev/zero of=/u02/app/oracle/oradata/TEST/datafile/o1_mf_tt_m7kvq4fy_.dbf bs=8192 conv=notrunc seek=2320 count=1 检查坏块: [oracle@test ~]$ dbv file=/u02/app/oracle/oradata/TEST/datafile/o1_mf_tt_m7kvq4fy_.dbf DBVERIFY: Release 19.0.0.0.0 - Production on Mon Jun 24 21:08:14 2024 Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved. DBVERIFY - Verification starting : FILE = /u02/app/oracle/oradata/TEST/datafile/o1_mf_tt_m7kvq4fy_.dbf Page 2180 is marked corrupt Corrupt block relative dba: 0x32400884 (file 201, block 2180) Completely zero block found during dbv: Page 2310 is marked corrupt Corrupt block relative dba: 0x32400906 (file 201, block 2310) Completely zero block found during dbv: Page 2320 is marked corrupt Corrupt block relative dba: 0x32400910 (file 201, block 2320) Completely zero block found during dbv: DBVERIFY - Verification complete Total Pages Examined : 2560 Total Pages Processed (Data) : 1873 Total Pages Failing (Data) : 0 Total Pages Processed (Index): 326 Total Pages Failing (Index): 0 Total Pages Processed (Other): 190 Total Pages Processed (Seg) : 0 Total Pages Failing (Seg) : 0 Total Pages Empty : 168 Total Pages Marked Corrupt : 3 Total Pages Influx : 0 Total Pages Encrypted : 0 Highest block SCN : 3492779 (0.3492779) 方法1: 简单的 row id的方式 1) 先取得坏块中ROW ID的最小值,执行以下的语句: 通过 dba_objects 和 dba_data_files 获取 SELECT dbms_rowid.rowid_create(1,<OBJ_ID>,<RFN>,<BL>,0) from DUAL; SELECT dbms_rowid.rowid_create(1,75003,201,2180,0) from DUAL; AAAST7ADJAAAAiEAAA SELECT dbms_rowid.rowid_create(1,75003,201,2310,0) from DUAL; AAAST7ADJAAAAkGAAA SELECT dbms_rowid.rowid_create(1,75003,201,2320,0) from DUAL; AAAST7ADJAAAAkQAAA 2)取得坏块中的ROW ID的最大值,执行以下的语句: SELECT dbms_rowid.rowid_create(1,<OBJ_ID>,<RFN>,<BL>+1,0) from DUAL; SELECT dbms_rowid.rowid_create(1,75003,201,2181,0) from DUAL; AAAST7ADJAAAAiFAAA SELECT dbms_rowid.rowid_create(1,75003,201,2311,0) from DUAL; AAAST7ADJAAAAkHAAA SELECT dbms_rowid.rowid_create(1,75003,201,2321,0) from DUAL; AAAST7ADJAAAAkRAAA 3)建议一个临时表存储那些没有坏块的数据,执行以下的语句: CREATE TABLE test AS SELECT * FROM testtest Where 1=2; 4)保存那些不存在坏块的数据到临时表中,执行以下的语句: INSERT INTO test SELECT /*+ ROWID(A) */ * FROM testtest A WHERE rowid < 'AAAST7ADJAAAAiEAAA'; INSERT INTO test SELECT /*+ ROWID(A) */ * FROM testtest A WHERE rowid >= 'AAAST7ADJAAAAiFAAA' and rowid<'AAAST7ADJAAAAkGAAA'; INSERT INTO test SELECT /*+ ROWID(A) */ * FROM testtest A WHERE rowid >= 'AAAST7ADJAAAAkHAAA' and rowid<'AAAST7ADJAAAAkQAAA'; INSERT INTO test SELECT /*+ ROWID(A) */ * FROM testtest A WHERE rowid >= 'AAAST7ADJAAAAkRAAA'; 5) 根据临时表中的数据重建表,重建表上的索引,限制。 方法2: 通过设置10231诊断事件可以在导出的时候让Oracle忽略表损坏的块,10231是Oracle的内部诊断事件,设置在全表扫描时跳过坏块的数据块, 只导出包含正确块的数据,之后把表删除,再把导出的表数据导入新表,从而修复该表。 SQL> ALTER SESSION SET EVENTS '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10'; Session altered. SQL> SQL> CREATE TABLE tt AS SELECT * FROM testtest; Table created. SQL> select count(*) from tt; COUNT(*) ---------- 73130 方法3: 设置系统event事件 然后导出(表比较大) ALTER SYSTEM SET EVENTS='10231 trace name context forever,level 10'; exp tt/tt file=/home/oracle/testtest.dmp tables=tt.testtest; [oracle@test ~]$ exp tt/tt file=/home/oracle/testtest.dmp tables=tt.testtest; Export: Release 19.0.0.0.0 - Production on Mon Jun 24 21:29:47 2024 Version 19.22.0.0.0 Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved. Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.22.0.0.0 Export done in US7ASCII character set and AL16UTF16 NCHAR character set server uses AL32UTF8 character set (possible charset conversion) About to export specified tables via Conventional Path ... . . exporting table TESTTEST 73130 rows exported EXP-00091: Exporting questionable statistics. Export terminated successfully with warnings. 删除表然后再导入。 完事后关闭 alter system set events='10231 trace name context off'; 方法4: 坏块较多,可以尝试如下过程(硬解析会比较高): set serveroutput on DECLARE TYPE extent_rec IS record (data_object_id number,relative_fno number,BLOCK_ID number,blocks number); t_extent extent_rec; bad_rows number := 0 ; error_code number; v_block_id number; v_rowid rowid; v_start_rowid rowid; v_end_rowid rowid; v_error_rowid rowid; v_sql1 varchar(1000):=''; v_sql2 varchar(1000):=''; ---坏块所在的用户表名 v_table VARCHAR(30):='TESTTEST'; v_owner VARCHAR(30):='TT'; ---获取段里面每个extent里面的block_id以及block数量,extent_id=0包含段头ID,要从段头ID之后开始 CURSOR c_extent IS select b.data_object_id,a.relative_fno,c.header_block+1 start_block_id,a.blocks-(c.header_block-a.block_id+1) from dba_extents a,dba_objects b,dba_segments c where a.segment_name=b.object_name and a.segment_name=c.segment_name and a.owner=c.owner and a.owner=b.owner and b.object_name=v_table and b.owner=v_owner and a.extent_id=0 union all select b.data_object_id,a.relative_fno,a.block_id start_block_id,blocks from dba_extents a,dba_objects b where a.segment_name=b.object_name and a.owner=b.owner and b.object_name=v_table and b.owner=v_owner and a.extent_id>0; BEGIN OPEN c_extent; LOOP FETCH c_extent INTO t_extent ; exit when c_extent%notfound; begin ---构造extent的最小开始rowid以及可能的最大rowid,660行是一个块里面最多存放的行数量 v_start_rowid:=dbms_rowid.rowid_create(1,t_extent.data_object_id,t_extent.relative_fno,t_extent.block_id,0); v_end_rowid:=dbms_rowid.rowid_create(1,t_extent.data_object_id,t_extent.relative_fno,t_extent.block_id+t_extent.blocks-1,660); ---按extent进行rowid数据扫描,将正常的数据插入test_tab_normal v_sql1:='insert into test_tab_normal select /*+ ROWID(A) */ * from '||v_owner||'.'||v_table||' A where rowid between '''||v_start_rowid||''' and '''||v_end_rowid||''''; execute immediate v_sql1; commit; ---如果按extent遇到报错或者查询数据失败则捕获异常转成按extent进行逐行的rowid扫描 exception when others then ---按rowid逐行进行检索,插入 test_tab_normal for a in 0..t_extent.blocks-1 loop v_block_id:=t_extent.block_id+a; for b in 0..660 loop begin v_rowid:=dbms_rowid.rowid_create(1,t_extent.data_object_id,t_extent.relative_fno,v_block_id,b); v_sql2:='insert into test_tab_normal select /*+ ROWID(A) */ * from '||v_owner||'.'||v_table||' A where rowid ='''||v_rowid||''''; execute immediate v_sql2; ---遇到坏块报错,插入bad_rows,由于是构造的rowid,可能会话插入很多的空行数据 exception when others then error_code:=sqlcode; if error_code in (-1410, -8103, -1578) then v_error_rowid:= v_rowid; bad_rows := bad_rows + 1; insert into bad_rows values(v_error_rowid, error_code||' block_id:'||v_block_id); commit; else raise; end if; end; end loop; commit; end loop; commit; END; END LOOP; commit; CLOSE c_extent; dbms_output.put_line('Total Bad Rows: '||bad_rows); END; / SQL> select count(*) from tt.test_tab_normal; COUNT(*) ---------- 73130 SQL> select count(*) from tt.bad_rows; COUNT(*) ---------- 4627 方法5: 通过rman方式进行恢复 少量坏块,可以直接恢复指定的坏块。 blockrecover datafile 201 block 2180; 大量坏块: backup validate datafile 201; blockrecover corruption list; https://blog.csdn.net/sinat_36757755/article/details/128985053 Extracting Data from a Corrupt Table using ROWID Range Scans (Doc ID 61685.1) Handling Oracle Block Corruptions (Doc ID 28814.1)
坏块的几种修复方式
来源:这里教程网
时间:2026-03-03 20:08:33
作者:
编辑推荐:
- oracle特殊恢复:BBED-SET命令03-03
- 坏块的几种修复方式03-03
- ClickHouse内幕(3)基于索引的查询优化03-03
- 速看!出大事儿啦!Oracle高可用掉链子,谁背锅?03-03
- Oracle常见监控(二)03-03
- oracle spa升级分析03-03
- 金仓数据库使用dblink访问ORACLE03-03
- oracle特殊恢复:BBED-SHOW/INFO/MAP命令03-03
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- ClickHouse内幕(3)基于索引的查询优化
ClickHouse内幕(3)基于索引的查询优化
26-03-03 - 速看!出大事儿啦!Oracle高可用掉链子,谁背锅?
速看!出大事儿啦!Oracle高可用掉链子,谁背锅?
26-03-03 - oracle特殊恢复:BBED-SHOW/INFO/MAP命令
oracle特殊恢复:BBED-SHOW/INFO/MAP命令
26-03-03 - Oracle、MySQL、达梦数据库GROUP BY语句对比
Oracle、MySQL、达梦数据库GROUP BY语句对比
26-03-03 - 数据库管理-第201期 优先级事务-01(20240611)
数据库管理-第201期 优先级事务-01(20240611)
26-03-03 - 异构数据库向南大通用GBase 8a迁移方案综述
异构数据库向南大通用GBase 8a迁移方案综述
26-03-03 - Oracle、MySQL、达梦数据库锁阻塞问题对比和解决
Oracle、MySQL、达梦数据库锁阻塞问题对比和解决
26-03-03 - 怎么解决远程主机强迫关闭了一个现有连接的问题
怎么解决远程主机强迫关闭了一个现有连接的问题
26-03-03 - 远程桌面无法连接,只需五步教你连接上远程桌面
远程桌面无法连接,只需五步教你连接上远程桌面
26-03-03 - 可拷,很刑!Autoupgrade升级Oracle如喝水...
可拷,很刑!Autoupgrade升级Oracle如喝水...
26-03-03
