资讯专栏INFORMATION COLUMN

实践篇—坏块处理方法

IT那活儿 / 2787人阅读
实践篇—坏块处理方法
点击上方“IT那活儿”,关注后了解更多精彩内容!!!
坏块的原因


造成数据块损坏的原因多种多样,可是因为物理原因导致,也可能人为原因或Oracle bug导致。


坏块的种类


物理坏块(也可以称为介质坏块)指的是块格式本身是坏的,块内的数据没有任何意义。

逻辑坏块,指的是块内的数据在逻辑是存在问题。(内容)


检查机制


物理一致性检查利用校验和字段工作,主要侧重于检查硬件故障并不关心内容正确与否。

逻辑一致性检查就是侧重于内容的检查,内容检查要比校验和检查复杂的多。



避免坏块


坏块不能避免,只能尽量减少发生坏块。                                                                


物理检查参数

通过设置初始化参数db_block_checksum=typical/full/false来启用、关闭物理一致性检查,启用该参数这会 增加1%~2%的负载,Oracle推荐启用该参数。在Oracle9i、10g中,默认是启用的。11g是typical。注意TRUE (implying TYPICAL)也就是说true<->typical。
在该参数设置为typical和full时,当读入时候重新计算校验和写出时候的校验对比,如果不同则认为是块损坏。如果设置为FULL模式,则基于update/delete应用程序语句级别的改变发生后,校验值会被重新计算并写入。同时对于日志块,在写入之前,同样会生产校 验值并写入到块头。该参数主要是防止IO硬件和IO子系统的错误。如果设置为OFF则只对系统表空间有效。
逻辑检查参数

通过设置参数db_block_checking=true可以启用数据块的逻辑一致性检查。启用该参数这会 增加1%~10%的负载,尤其DML操作越密集性能影响越大。在Oracle10g中这个参数 默认值是false,这将意味这数据库只对System表空间做逻辑一致性检查。
模拟坏块

物理坏快通过dd即可,逻辑坏块需要通过bbed这些非oracle官方支持的工具模拟
此处模拟物理坏块,注意,在没有备份的情况下,物理坏块基本无救,但是我们需要对坏块进行跳过处理。(通过dul,bbed来恢复。)

</>复制代码

  1. >create tablespace crpt_ts datafile /u01/app/oracle/oradata/orcl/crpt_ts.dbf size 100M;
    >create table scott.crpt tablespace crpt_ts as select * from dba_objects where rownum <3000;
    > select distinct dbms_rowid.rowid_block_number(rowid) b_no ,dbms_rowid.rowid_relative_fno(rowid) f_no from scott.crpt order by 1;

          B_NO F_NO
    ---------- ----------
           131      7
           132      7
    ……………………省略……………………………..
           171      7

    39 rows selected.
    SYS@ orcl>select a.file_id,a.block_id,a.blocks,b.name from dba_extents a,v$datafile b where a.file_id=b.file# and a.owner=SCOTT and a.segment_name=CRPT order by a.block_id;

       FILE_ID BLOCK_ID BLOCKS NAME
    ---------- ---------- ---------- --------------------------------------------------
       7    128         8 /u01/app/oracle/oradata/orcl/crpt_ts.dbf
       7    136         8 /u01/app/oracle/oradata/orcl/crpt_ts.dbf
       7    144         8 /u01/app/oracle/oradata/orcl/crpt_ts.dbf
       7    152         8 /u01/app/oracle/oradata/orcl/crpt_ts.dbf
       7    160         8 /u01/app/oracle/oradata/orcl/crpt_ts.dbf
       7    168         8 /u01/app/oracle/oradata/orcl/crpt_ts.dbf
    6 rows selected.
    ---破坏137,158 数据块的内容
    seek=n从输出文件开头跳过 n个blocks 个块后再开始复制。
    conv=notrunc不截短输出文件
    dd if=/dev/zero of=/u01/app/oracle/oradata/orcl/crpt_ts.dbf bs=8192 conv=notrunc seek=137 count=1
    dd if=/dev/zero of=/u01/app/oracle/oradata/orcl/crpt_ts.dbf bs=8192 conv=notrunc seek=158 count=1
    也可以这样:
    • dd of=/u01/app/oracle/oradata/orcl/crpt_ts.dbf bs=8192 conv=notrunc seek=158 <• > Corrupt me!
    > EOF


此时dbv命令已经可以检查出两个坏块了:


</>复制代码

  1. [oracle@cuug101 script]$ dbv file=/u01/app/oracle/oradata/orcl/crpt_ts.dbf

    DBVERIFY: Release 11.2.0.4.0 - Production on Tue May 15 16:25:24 2018

    Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
    …………………省略………………….
    Total Pages Empty            : 12629
    Total Pages Marked Corrupt : 2
    Highest block SCN            : 12592990 (0.12592990)


启动数据库已经发现无法对有坏块的对象进行全表扫描:


</>复制代码

  1. SYS@ orcl>select count(*) from scott.crpt;
    select count(*) from scott.crpt
    *
    ERROR at line 1:
    ORA-01578: ORACLE data block corrupted (file # 7, block # 137)
    ORA-01110: data file 7: /u01/app/oracle/oradata/orcl/crpt_ts.dbf


通过告警日志看出数据库在file 7block 137中的checksum的值和读取时重新计算的值已经不同,由于两次checksum值不同(即异或结果为非0),说明数据块被修改过,数据块为坏块(corruption)。

alert.log中的相关信息。

</>复制代码

  1. ORA-01578: ORACLE data block corrupted (file # 7, block # 137)
    ORA-01110: data file 7: /u01/app/oracle/oradata/orcl/crpt_ts.dbf
    Hex dump of (file 7, block 158) in trace file /u01/app/oracle/diag/rdbms/orcl/orcl/incident/incdir_259354/orcl_m000_5108_i259354_a.trc
    Corrupt block relative dba: 0x01c0009e (file 7, block 158)
    Completely zero block found during validation
    SYS@ orcl>select * from v$database_block_corruption;
    FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO
    ---------- ---------- ---------- ------------------ ---------
    7   137        1   0 ALL ZERO
    7   158        1   0 ALL ZERO
解决,查看块的对象,这里很明显是个表对象,如果是索引可以重建,如果是表,则有可能会丢数据,

</>复制代码

  1. SELECT OWNER, SEGMENT_NAME, SEGMENT_TYPE, TABLESPACE_NAME
    FROM DBA_EXTENTS A
    WHERE FILE_ID = 7
    AND 137 BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS - 1
    /

    OWNER SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME
    ------------------------------ -------------------- ------------------ ------------------------------
    SCOTT CRPT TABLE        CRPT_TS
如果是表,则先进行修复块,如果修复失败,则可以通过设置事件跳过坏块,然后在imp回去,我们用dbms_repair来跳过这个坏块(实际上如果只是checksum坏了,可以修改checksum为正确的值。但实际情况下,checksum坏了往往意味着坏内的数据已经坏了,大多数情况下只能丢弃),exp和dbms_repair都只是跳过坏块,但是还是数据丢失。如果有备份,则选择用备份恢复,毕竟备份的数据没有问题(没有坏块),如果没备份,通过设置事件来在exp的过程中跳过坏块导出表,在重新导入expdp 自动检测到坏块并跳过坏块,注意expdp虽然可以跳过坏块,但是如果坏的是段头,则导出的数据失败。

</>复制代码

  1. [oracle@cuug101 ~]$ exp system/oracle file=crpt.dmp tables=scott.crpt

    [oracle@cuug101 ~]$ expdp system/oracle dumpfile=crpt.dmp tables=scott.crpt

    Export: Release 11.2.0.4.0 - Production on Tue May 15 23:49:52 2018

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

    . . exporting table                           TEST
    EXP-00056: ORACLE error 1578 encountered
    ORA-01578: ORACLE data block corrupted (file # 7, block # 137)
    ORA-01110: data file 4: /u01/app/oracle/oradata/orcl/users01.dbf
    Export terminated successfully with warnings.
    SYS@ orcl>alter system  set events=10231 trace name context forever,level 10;
注意:导完以后别忘记关闭事件

</>复制代码

  1. alter system set events=10231 trace name context off;
    System altered.
    [oracle@cuug101 exp]$ expdp system/oracle dumpfile=crpt.dmp tables=scott.crpt
    Processing object type TABLE_EXPORT/TABLE/TABLE
    . . exported "SCOTT"."CRPT"                              262.7 KB 2842 rows
    Master table "SYSTEM"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
    [oracle@cuug101 exp]$ impdp system/oracle dumpfile=crpt.dmp remap_table=scott.crpt:crpt1
    Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
    . . imported "SCOTT"."CRPT1"                           262.7 KB 2842 rows
注意原有的表空间里面对应的数据文件还是坏块,此时 可以将导出的表空间的数据,通过remap_tablespace=crpt:crpt1-------------crpt1表空间需要先建立。
remap_schema=scott:scott1------------scott1用户需要先建立。(当然了因为crpt的所有对象都属于scott,所以只需要执行一个scott:scott1),如果还有其他用户的表,可以remap_schema=scott:scott1,sun:sun1
这样crpt1的数据就跟crpt一样,直接删除crpt表空间即可。
使用dbms_repair


</>复制代码

  1. SYS@ orcl>select table_name, skip_corrupt from dba_tables where table_name = CRPT AND owner=SCOTT;
    TABLE_NAME SKIP_COR
    ------------------------------ --------
    CRPT DISABLED


创建管理表


</>复制代码

  1. set serveroutput on
    begin
    dbms_repair.admin_tables (
    table_name => REPAIR_TABLE,
    table_type => dbms_repair.repair_table,
    action => dbms_repair.create_action,
    tablespace => CRPT_TS);
    end;
    /


检查坏块


</>复制代码

  1. declare

    rpr_count int;
    begin
    rpr_count := 0;
    dbms_repair.check_object (
    schema_name => SCOTT,
    object_name => CRPT,
    repair_table_name => REPAIR_TABLE,
    corrupt_count => rpr_count);
    dbms_output.put_line(repair count:  || to_char(rpr_count));
    end;
    repair count:2


查看损坏块的信息


</>复制代码

  1. SYS@ orcl>col object_name for a20
    SYS@ orcl>col CORRUPT_DESCRIPTION for a50
    SYS@ orcl>col REPAIR_DESCRIPTION for a40
    SYS@ orcl>col CORRUPT_DESCRIPTION for a20
    SYS@ orcl>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
    -------------------- ---------- ------------ ---------- -------------------- ----------------------------------------
    CRPT 137 6148 TRUE      mark block software corrupt
    CRPT 158 6148 TRUE      mark block software corrupt


1. 定位坏块:只有将坏块信息写入定义的REPAIR_TABLE后,才能处理坏块。


</>复制代码

  1. (skip/noskip)

    SYS@ orcl> declare
    fix_count int;
    begin
    fix_count := 0;
    dbms_repair.fix_corrupt_blocks (
    schema_name => SCOTT,
    object_name => CRPT,
    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;
    SYS@ orcl>/
    fix count: 0

    PL/SQL procedure successfully completed.
2. 跳过坏块:我们前面虽然定位了坏块,但是,如果我们访问这个表还是会得到错误信息,所以需要skip处理。

</>复制代码

  1. begin
    dbms_repair.skip_corrupt_blocks (
    schema_name => SCOTT,
    object_name => CRPT,
    object_type => dbms_repair.table_object,
    flags => dbms_repair.skip_flag);
    end;
    8     /

    PL/SQL procedure successfully completed.

    SYS@ orcl>select table_name, skip_corrupt from dba_tables where table_name = CRPT AND owner=SCOTT;

    TABLE_NAME SKIP_COR
    ------------------------------ --------
    CRPT ENABLED

    select count(*) from crpt;


    SYS@ orcl>select count(*) from scott.crpt;

    COUNT(*)
    ----------
    2842
3. rman中有blockrecover来恢复坏块,但是如果没有备份无法实现。
---使用rman检查数据文件是否有坏块

</>复制代码

  1. backup check logical validate datafile 500;

    RMAN> backup check logical validate datafile 500;

    Starting backup at 02-MAR-21
    using target database control file instead of recovery catalog
    allocated channel: ORA_DISK_1
    channel ORA_DISK_1: SID=8190 instance=cxbdzxdb1 device type=DISK
    channel ORA_DISK_1: starting full datafile backup set
    channel ORA_DISK_1: specifying datafile(s) in backup set
    input datafile file number
    =00500 name=+DG_DATA_SSD_2/CXBDZXDB/DATAFILE/tbs_index.257.1065130555
    channel ORA_DISK_1: backup set complete, elapsed time: 00:01:36
    List of Datafiles
    =================
    File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
    ---- ------ -------------- ------------ --------------- ----------
    500  FAILED 0              145285       3932160         11215813018512
    File Name: +DG_DATA_SSD_2/CXBDZXDB/DATAFILE/tbs_index.257.1065130555
    Block Type Blocks Failing Blocks Processed
    ---------- -------------- ----------------
    Data 0              1657837
    Index 1              2124520
    Other 0              4518

    validate found one or more corrupt blocks
    See trace file /oracle/app/oracle/diag/rdbms/cxbdzxdb/cxbdzxdb1/trace/cxbdzxdb1_ora_35457316.trc for details
    Finished backup at 02-MAR-21


--执行完成后执行


</>复制代码

  1. set line 300
    select * from V$database_block_corruption;
    SQL> set line 300
    SQL> select * from V$database_block_corruption;
    FILE#     BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTION_TYPE CON_ID
    ---------- ---------- ---------- ------------------ ------------------ ----------
    500 1042393 1 1.1216E+13 CORRUPT 0


---查询文件号对应的数据文


</>复制代码

  1. select 
    file_id,FILE_NAME,TABLESPACE_NAME,BYTES/1024/1024,STATUS,AUT
    OEXTENSIBLE,ONLINE_STATUS from dba_data_files where 
    file_id=856;
---查询索引对应的table

</>复制代码

  1. set linesize 300
    col owner for a30
    col table_name for a30
    col index_name for a30
    col partitioned for a30
    select owner,table_name,index_name,status,partitioned,uniqueness,tablespace_name from dba_indexes where  owner=POLICY and index_name=IDX_PLC_RATION_TOPID order by 3;
---读取索引ddl语句

</>复制代码

  1. set long 3000
    select 
    dbms_metadata.get_ddl(INDEX,IDX_PLC_RATION_TOPID,POLICY
    ) a from dual;
-----重建索引

</>复制代码

  1. drop index policy.IDX_PLC_RATION_TOPID;
    CREATE INDEX "POLICY"."IDX_PLC_RATION_TOPID" ON 
    "POLICY"."PLC_RATION" ("TOPID") TABLESPACE "TBS_INDEX" 
    parallel 12 ;
----坏块查询
4. 通过dbv和rman blockrecover对Oracle数据库坏块进行修复。
(1)rman备份时alert.log报如下错误:

</>复制代码

  1. Fri Jul 2 12:41:36 2010
    Hex dump of (file 12, block 2718618) in trace file /u01/app/oracle/admin/bi/udump/bi_ora_31213.trc
    Corrupt block relative dba: 0x03297b9a (file 12, block 2718618)
    Fractured block found during backing up datafile
    Data in bad block:
    type: 6 format: 2 rdba: 0x03297b9a
    last change scn: 0x0002.482fc15b seq: 0x1 flg: 0x06
    spare1: 0x0 spare2: 0x0 spare3: 0x0
    consistency value in tail: 0x77b20601
    check value in block header: 0x253
    computed block checksum: 0xb6e9
    Reread of blocknum=2718618, file=/u01/oradata/BI/estaging_user01.712.714072365. found same corrupt data
    Reread of blocknum=2718618, file=/u01/oradata/BI/estaging_user01.712.714072365. found same corrupt data
    Reread of blocknum=2718618, file=/u01/oradata/BI/estaging_user01.712.714072365. found same corrupt data
    Reread of blocknum=2718618, file=/u01/oradata/BI/estaging_user01.712.714072365. found same corrupt data
    Reread of blocknum=2718618, file=/u01/oradata/BI/estaging_user01.712.714072365. found same corrupt data


(2)查询数据库,可知含有坏块的对象:


</>复制代码

  1. SQL> col SEGMENT_NAME format a20
    col PARTITION_NAME format a10
    select owner,segment_name,partition_name from dba_extents where file_id = 12 and 2718618 between block_id and block_id + blocks-1;
    OWNER SEGMENT_NAME PARTITION_
    -------------------- -------------------- ----------
    ESTAGING LOG_RECORD_DETAIL_4 P20100630


(3)但全表扫描却没有任何问题:


</>复制代码

  1. SQL> select count(*) from ESTAGING.LOG_RECORD_DETAIL_4 partition (P20100630);
    COUNT(*)
    ----------
    449937
    SQL> select count(*) from ESTAGING.LOG_RECORD_DETAIL_4
    ;
    COUNT(*)
    ----------
    42049608


(4)使用dbv检查发现有一个坏块(耗时较长):


</>复制代码

  1. $ dbv file=/u01/oradata/BI/estaging_user01.712.714072365 BLOCKSIZE=8192
    DBVERIFY: Release 10.2.0.4.0 - Production on Fri Jul 2 14:15:49 2010
    Copyright (c) 1982, 2007, Oracle. All rights reserved.
    DBVERIFY - Verification starting : FILE = /u01/oradata/BI/estaging_user01.712.714072365
    Page 2718618 is influx - most likely media corrupt
    Corrupt block relative dba: 0x03297b9a (file 12, block 2718618)
    Fractured block found during dbv:
    Data in bad block:
    type: 6 format: 2 rdba: 0x03297b9a
    last change scn: 0x0002.482fc15b seq: 0x1 flg: 0x06
    spare1: 0x0 spare2: 0x0 spare3: 0x0
    consistency value in tail: 0x77b20601
    check value in block header: 0x253
    computed block checksum: 0xb6e9
    DBVERIFY - Verification complete
    Total Pages Examined : 2748160
    Total Pages Processed (Data) : 2462446
    Total Pages Failing (Data) : 0
    Total Pages Processed (Index):235234
    Total Pages Failing (Index):0
    Total Pages Processed (Other):24969
    Total Pages Processed (Seg) : 0
    Total Pages Failing (Seg) : 0
    Total Pages Empty : 25510
    Total Pages Marked Corrupt : 1
    Total Pages Influx : 1
    Highest block SCN : 1229607770 (2.1229607770)


(5)使用rman检查含有坏块的数据文件(耗时较长),, 期间观察alert.log会发现同样的提示:


</>复制代码

  1. RMAN> backup validate datafile 12;
    这个时候访问v$database_block_corruption可以看到详细的坏块的信息:
    SQL> select * from v$database_block_corruption;
    FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO
    ---------- ---------- ---------- ------------------ ---------
    12 2718618 1 0 FRACTURED
(6)使用rman进行块恢复:

</>复制代码

  1. RMAN> blockrecover datafile 12 block 2718618 from backupset;
(7)块恢复后,执行BLOCKRECOVER CORRUPTION LIST,会自动按照V$DATABASE_BLOCK_CORRUPTION进行修复(耗时较长):

</>复制代码

  1. RMAN> BLOCKRECOVER CORRUPTION LIST;
(8)这个时候再访问v$database_block_corruption就看不到详细的坏块信息了:

</>复制代码

  1. SQL> select * from v$database_block_corruption;
    no rows selected


(9)再使用dbv检查发现没有坏块了(耗时较长):


</>复制代码

  1. $ dbv file=/u01/oradata/BI/estaging_user01.712.714072365 BLOCKSIZE=8192
    DBVERIFY: Release 10.2.0.4.0 - Production on Fri Jul 2 15:38:15 2010
    Copyright (c) 1982, 2007, Oracle. All rights reserved.
    DBVERIFY - Verification starting : FILE = /u01/oradata/BI/estaging_user01.712.714072365
    DBVERIFY - Verification complete
    Total Pages Examined : 2749440
    Total Pages Processed (Data) : 2463763
    Total Pages Failing (Data) : 0
    Total Pages Processed (Index):235250
    Total Pages Failing (Index):0
    Total Pages Processed (Other):24981
    Total Pages Processed (Seg) : 0
    Total Pages Failing (Seg) : 0
    Total Pages Empty : 25446
    Total Pages Marked Corrupt : 0
    Total Pages Influx : 0
    Highest block SCN : 1230819157 (2.1230819157)


注意如果没有rman的备份,无法执行上面的语句,退一步讲,如果这是你有手工的热备,可以将热备catalog datafilecopy xxxxxx;转换成一个rman备份。

然后也可以用blockrecover了。

本 文 原 创 来 源:IT那活儿微信公众号(上海新炬王翦团队)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/129729.html

相关文章

  • 微软为OCP计算项目推出云SSD存储新规范

    摘要:微软正在继续向提交潜在的新规范。微软方面表示,预计在未来几个月内完成规范,并在今年晚些时候推出。此外,微软还在推进另一个开放计算贡献的项目。去年年底,微软推出了加密微控制器标准。微软正在继续向Open Compute Project提交潜在的新规范。在美国圣何塞举行的Open Compute Project(OCP)美国峰会上,微软推出了Project Denali,一项用于SSD固件接口标...

    mmy123456 评论0 收藏0
  • 利用Oracle ADG升级11.2.0.4到19.8案例分享

    利用Oracle ADG升级11.2.0.4到19.8案例分享 img{ display:block; margin:0 auto !important; width:100%; } body{ width:75...

    IT那活儿 评论0 收藏1380
  • Java异常处理 10 个最佳实践

    摘要:为可恢复的错误使用检查型异常,为编程错误使用非检查型错误。检查型异常保证你对错误条件提供异常处理代码,这是一种从语言到强制你编写健壮的代码的一种方式,但同时会引入大量杂乱的代码并导致其不可读。在编程中选择检查型异常还是运行时异常。 异常处理是Java 开发中的一个重要部分。它是关乎每个应用的一个非功能性需求,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等。Java提供了...

    Forelax 评论0 收藏0
  • Java 异常处理的 9 个最佳实践

    摘要:异常处理的个最佳实践原文地址翻译出处在中,异常处理是个很麻烦的事情。使用描述性消息抛出异常这个最佳实践背后的想法与前两个类似。当你以错误的格式提供时,它将被类的构造函数抛出。类提供了特殊的构造函数方法,它接受一个作为参数。 Java 异常处理的 9 个最佳实践 原文地址:https://dzone.com/articles/9-...翻译出处:https://www.oschina.n...

    sihai 评论0 收藏0

发表评论

0条评论

IT那活儿

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<