【Oracle资源破坏类故障】:具体相识坏块

[复制链接]
发表于 2025-10-11 22:26:33 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次
1、物理坏块与逻辑坏块
1.1、物理坏块
1.2、逻辑坏块
2、两个坏块相干的参数
2.1、db_block_checksum
2.2、db_block_checking
3、检测坏块 
3.1、告警日记
3.2、RMAN
3.3、ANALYZE
3.4、数据字典
3.5、DBVERIFY
4、修复坏块
4.1、RMAN修复
4.2、DBMS_REPAIR修复
4.3、BBED
5、写在末了

1、物理坏块与逻辑坏块

        将数据库比喻成一本书,每一页看作是一个数据块。当我们看不懂书中某页的内容大概有3种缘故原由:该页缺损、该页内容逻辑有错误、智商不敷。我们的智商显然不是标题,这点起首清除。
        以是书页缺损、书页上的内容逻辑错误是最大概的两点缘故原由。此中页书缺损就好比数据库中的物理坏块,直接粗暴的粉碎了这一页;书页上的内容逻辑错误就像是数据库中的逻辑坏块,写的内容驴头不对马嘴。
        假如如今写的这篇文章让您读着不通顺大概读不懂,那这篇文章也属于是个逻辑坏块。
1.1、物理坏块

        存储介质导致的数据块破坏,常见的场景是磁盘破坏、网络故障导致数据块在传输时发生破坏,突然断电导致数据块的元数据破坏。
1.1.1、物理坏块的常见错误体现
1.1.1.1、Fractured Block(断块)
        断块是指数据块不完备,块头信息与块尾信息不匹配。
   Corrupt block relative dba: 0x0380e573 (file 14, block 58739)
  Fractured block found during buffer read
  Data in bad block -
  type: 6 format: 2 rdba: 0x0380e573
  last change scn: 0x0288.8e5a2f78 seq: 0x1 flg: 0x04
  consistency value in tail: 0x00780601
  check value in block header: 0x8739, computed block checksum: 0x2f00
  spare1: 0x0, spare2: 0x0, spare3: 0x0
  ***
  Reread of rdba: 0x0380e573 (file 14, block 58739) found same corrupted data
  1.1.1.2、Bad checksum
        这个错误是指checksum差异等。
        checksum是数据块的校验和,它是Oracle将数据块中的内容通某种算法举行盘算天生的一个唯一的校验值。checksum存储在数据块的头部;当读取数据块时,Oracle会重新盘算checksum,与存储在数据块头部的checksum举行比力,假如差异等,就判定数据块发生了破坏。
   Corrupt block relative dba: 0x0380a58f (file 14, block 42383)
  Bad check value found during buffer read
  Data in bad block -
  type: 6 format: 2 rdba: 0x0380a58f
  last change scn: 0x0288.7784c5ee seq: 0x1 flg: 0x06
  consistency value in tail: 0xc5ee0601
  check value in block header: 0x68a7, computed block checksum: 0x2f00
  spare1: 0x0, spare2: 0x0, spare3: 0x0
  ***
  Reread of rdba: 0x0380a58f (file 14, block 42383) found same corrupted data
  1.1.1.3、Block Misplaced
        Oracle检测到正在读取的数据块的内容属于另一个块,但是checksum有效。
    Corrupt block relative dba: 0x0d805a89 (file 54, block 23177)
  Bad header found during buffer read
  Data in bad block -
  type: 6 format: 2 rdba: 0x0d805b08 ----> Block is different than expected 0x0d805a89
  last change scn: 0x0692.86dc08e3 seq: 0x1 flg: 0x04
  consistency value in tail: 0x08e30601
  check value in block header: 0x2a6e, computed block checksum: 0x0
  spare1: 0x0, spare2: 0x0, spare3: 0x0
  1.1.1.4、Zeroed out blocks
        假如Oracle数据库发生了Zeroed out blocks,那么根本可以判定是使用体系大概存储体系发生了故障。
        根据Oracle官方文档形貌,在计划的时间,Oracle就被确定不会写全零块,目的是为了辨认底层使用体系大概存储中的故障。
   Corrupt block relative dba: 0x014000a0 (file 5, block 160)
  Completely zero block found during multiblock buffer read
  
1.2、逻辑坏块

        逻辑坏块是指数据块的内容大概结构不符合Oracle内部规范,但是在物理存储介质方面没有标题。固然发生了逻辑坏块,但其checksum很大概并无标题,只是数据块中的内容发生了破坏。
        逻辑坏块的具体破坏形貌通常不会输出到告警日记中,这点是和物理坏块差异的。
1.2.1、逻辑坏块常见错误体现:
1.2.1.1、ORA-600 [4512]
   ORA-600 [4512],被不存在的事件锁定了行。
  1.2.1.2、不符合自然逻辑
   日期数据范例字段,存入了2025-03-32 25:61:61这种不符合自然逻辑的数据。
  1.2.1.3、数据字典逻辑破坏
Oracle数据字典字典表发生了字典数据与现实差异等的环境;比方:dba_tables体现某表存在,但是现实的数据文件没有这个表段。
   实验DDL使用时,触发ORA-00600 [kdsgrp1],大概元数据查询失败。
  1.2.1.4、索引失效
索引指向了无效的ROWID,好比说数据行已经被删除了,但是索引没有更新。
   索引扫描时,返回ORA-01410(无效的ROWID),大概查询结果不匹配。
  1.2.1.5、数据块头部元数据破坏
数据块的头部信息,比方块的范例、SCN、事件槽遭到破坏。比方数据块的范例原来是表段块,但是现实存储的却是索引,这种错误就属于是Oracle软件的bug了。
   访问到这种逻辑坏块时,触发ORA-00600 [kddummy_blkchk]内部错误。
  
2、两个坏块相干的参数

2.1、db_block_checksum

        这个参数是用来控制checksum的天生.
        checksum是数据块的校验和,它是Oracle将数据块中的内容通某种算法举行盘算天生的一个唯一的校验值。checksum存储在数据块的头部;当读取数据块时,Oracle会重新盘算checksum,与存储在数据块头部的checksum举行比力,假如差异等,就判定数据块发生了破坏。
        可以通过show parameter来查察当前数据库对于此参数的设置环境。
  1. SQL> show parameter db_block_checksum
  2. NAME                                     TYPE         VALUE
  3. ------------------------------------ ----------- ------------------------------
  4. db_block_checksum                     string         TYPICAL
复制代码
        db_block_checksum参数有3种选项:FULL、TYPICAL、OFF,下面临这三种选项举行简单阐明。
参数选项简单阐明
FULL对全部数据块,包罗数据文件、控制文件、日记文件天生校验和。
TYPICAL默认值,对数据文件、控制文件天生校验和,不会作用于临时表空间。
OFF不天生checksum,这个是不保举的。
        可以修改db_block_checksum参数,但由于是静态参数,修改完参数必要重启数据库。
  1. ALTER SYSTEM SET db_block_checksum = FULL SCOPE=SPFILE;
复制代码
2.2、db_block_checking

        这个参数是对数据块的逻辑划一性查抄,当数据块在被读取大概修改时,自动检测数据块内部结构的逻辑错误,从而防止由于逻辑破坏导致数据丢失。
        db_block_checking参数有4种选项:HIGH、MEDIUM、LOW、OFF,下面临这4种选项举行简单的阐明。
参数选项简单阐明
HIGH实验完备的逻辑查抄,包罗索引块、事件槽,覆盖数据库全部的修改使用。
MEDIUM对全部表空间的数据块实验根本查抄,比方块头等。
LOW只对数据库的体系表空间实验数据块查抄。
OFF不对任何数据块实验查抄,这是个默认值。
        可以修改db_block_checking参数,但由于是静态参数,修改完参数必要重启数据库。
  1. ALTER SYSTEM SET db_block_checking=HIGH SCOPE=SPFILE;
复制代码

       db_block_checksum与db_block_checking参数的差异点在于db_block_checksum是用来检测物理完备性的,重要是服务于物理坏块标题处理惩罚;db_block_checking是用来检测逻辑划一性的,重要是服务于逻辑坏块标题处理惩罚。
        db_block_checksum与db_block_checking参数的类似点是当启用参数时,启用的级别的越高,对性能的影响就会越大。以是在使用这两个参数时,必要在数据库性能和数据安全这两方面做好平衡。

3、检测坏块 

        Oracle数据库提供了几种本事可以对坏块举行监测,下面临这些本事举行逐一先容。这些本事侧重点和使用场景都有差异,有的也可以组合使用,服从结果更佳。
3.1、告警日记

        告警日记是DBA最常看的日记,每次巡检假如绕开它,个人以为都不算一次标准的巡检。Oracle在检测到数据坏块时,会在告警日记中记载错误信息。通过查抄告警日记,可以实时发现数据坏块错误。
        确定告警日记位置,以下两个方法都可以。
  1. SQL> show parameter dump
  2. NAME                                     TYPE         VALUE
  3. ------------------------------------ ----------- ------------------------------
  4. background_core_dump                     string         partial
  5. background_dump_dest                     string         /oracle/app/diag/rdbms/htbase/htbase1/trace
  6. core_dump_dest                                 string         /oracle/app/diag/rdbms/htbase/htbase1/cdump
  7. max_dump_file_size                         string         unlimited
  8. shadow_core_dump                         string         PARTIAL
  9. user_dump_dest                                 string         /oracle/app/diag/rdbms/htbase/htbase1/trace
  10. SQL> SELECT value FROM v$diag_info WHERE name = 'Diag Trace';
  11. VALUE
  12. --------------------------------------------------------------------------------
  13. /oracle/app/diag/rdbms/htbase/htbase1/trace
复制代码
        检索坏块错误记载
        在告警日记中搜索“ORA-01578”,大概搜素“Corrupt block“关键字。这个各人可以看上文物理坏块先容那边就知道为什么检索两个了。
3.2、RMAN

        RMAN也是官方保举坏块检测工具,支持对数据文件、控制文件、归档日记文件等举行完备性查抄,个人以为RMAN比力适看成为一种定期康健查抄的本事。RMAN有下面几种查抄方式。
3.2.1、查抄整个数据库
        可以输出全部数据文件、控制文件、日记文件的坏块信息。
  1. RMAN> VALIDATE DATABASE;
复制代码
3.2.2、查抄指定的数据文件
        可以输出数据文件内每个块的物理和逻辑划一性。
  1. RMAN> VALIDATE DATAFILE 28;  -- 文件号为28的数据文件
复制代码
3.2.3、逻辑划一性查抄
        不光查抄数据块的物理完备性,还会查抄数据块的逻辑结构。
  1. RMAN> VALIDATE CHECK LOGICAL DATABASE;
复制代码
3.2.4、查抄备份集
        这个下令,无论是新手还是老手都不陌生,备份常用下令,查抄备份文件是否破坏,确保规复的时间是可用的。
  1. RMAN> VALIDATE BACKUPSET <备份集编号>;
复制代码
3.3、ANALYZE

ANALYZE下令可以查抄表、索引的逻辑划一性。
3.3.1、查抄表结构
        假如存在坏块,会抛出ORA-01498错误。此时大概是数据块头部的元数据信息堕落、索引对应数据块的关联关系有误(这些都在上文的逻辑坏块部分先容过);假如是物理坏块,还会伴随着ORA-01578。
  1. ANALYZE TABLE hr.zqd VALIDATE STRUCTURE;
复制代码
3.3.2、查抄索引的划一性
        假如索引与表数据不匹配,会抛出ORA-01499错误。这大概是索引和表数据没同步,比方删除大量数据后,没有重修索引;事件非常制止导致索引条目没有正常更新等等。假如是物理破坏的话,会伴随着ORA-01578错误。
        此时比力高效的修复使用是重修索引,但不肯定能办理全部场景下的此类标题。
  1. ANALYZE INDEX HR.zqd_idx VALIDATE STRUCTURE;
复制代码
3.4、数据字典

3.4.1、V$DATABASE_BLOCK_CORRUPTION
  1. SELECT * FROM V$DATABASE_BLOCK_CORRUPTION;
复制代码
        这个视图会记载Oracle数据库中检测到坏块信息。这个视图的数据写入触发机制包罗以下几种途径。
使用具体使用
RAMN 1、使用RMAN举行备份的时间,会验证数据块的完备性,若发现坏块,会写入该视图。
2、使用RMAN举行VALIDATE验证时,若发现坏块,会写入该视图。
3、使用RMAN举行RECOVER规复时,若发现坏块,会写入该视图。
进程检测 1、读取数据时,checksum差异等,会将坏块信息写入该视图。
2、SELECT语句访问到坏块时,会将坏块信息写入该视图。
工具查抄 1、DBVERIFY作为外部工具,不会直接将坏块信息写入视图,但可以通过日记文件手动确认坏块后,必要通过数据库使用才会将坏块信息写入视图。
2、ANALYZE下令若检测到坏块大概会将坏块信息写入视图。
3.4.2、DBA_EXTENTS
        通过这个Oracle体系底子表,可以定位到具体的坏块所在对象,大概是表、索引、大字段。
  1. SELECT owner, segment_name, segment_type
  2. FROM dba_extents
  3. WHERE file_id = 5    -- 文件号
  4.   AND 1234 BETWEEN block_id AND block_id + blocks -1;  -- 块号
复制代码
3.5、DBVERIFY

        DBVERIFY是Oracle数据库提供的下令行工具,用于查抄数据文件物理和逻辑划一性,重点查抄数据块的完备性。
3.5.1、DBVERIFY有几个特点,重要包罗以下几个方面。
3.5.1.1、只读方式打开
        它以只读的方式打开数据文件,不会修改数据文件,确保了数据文件的安全性。
3.5.1.2、在线查抄
        它支持在线查抄数据文件,不必要关闭数据库。固然离线时对数据文件的查抄速率更快。
3.5.1.3、支持对ASM文件的查抄
        在数据库是正常打开的环境下,通过userid参数指定用户权限,即可查抄ASM文件。
  1. dbv file=+DG1/orcl/datafile/system01.dbf userid=system/sys
复制代码
3.5.2、DBVERIFY是有范围性的,重要包罗以下几个方面:
3.5.2.1、只查抄数据文件
        它只能查抄数据文件;不能查抄控制文件和日记文件。
3.5.2.2、不查抄逻辑关联性
        只会查抄数据块内部的结构,不会查抄索引与表数据的匹配关系。
3.5.2.3、文件巨细限定
        在某些平台下,不能查抄凌驾2G的数据文件(但这一点我本身没有现实验证过)。
3.5.3、常用与资助
        DBVERIFY工具的下令参数有很多,但常用的就是FILE、BLOCKSIZE、LOGFILE等。假如有特别必要可以查察资助:dbv help=y
  1. dbv FILE=/oradata/users01.dbf BLOCKSIZE=8192 LOGFILE=/tmp/dbv.log
复制代码

4、修复坏块

4.1、RMAN修复

        最抱负的是使用RMAN规复,进而实现修复坏块的目的。但这是必要当前数据库有备份,而且备份可用无坏块的环境下。
4.1.1、使用RMAN举行块规复
        检测到数据库的坏块、坏块所在数据文件后,可以指定坏块举行块规复。发起是在数据库坏块不多的环境下使用块规复,这种修复服从很高;假如是规复整个数据文件,规复服从会相对很低。
  1. RMAN> VALIDATE BACKUPSET ALL; --查抄全部备份集是否可用,且有无坏块。RMAN> VALIDATE BACKUPSET <备份集编号>; --指定备份集举行查抄,查抄是否可用,且有无坏块。
复制代码
  1. RMAN> VALIDATE DATABASE; --检测坏块位置
复制代码
  1. RMAN> blockrecover datafile 4 block 1798; --进行块恢复
  2. --也可以一次修复同一数据文件中的多个坏块
  3. RMAN> blockrecover datafile 4 block 1798,1799; --进行多个坏块恢复
复制代码
  1. VALIDATE DATAFILE 4 BLOCK 1798; --验证修复结果
复制代码
4.1.2、使用RMAN举行数据文件规复
        假如数据库中的坏块很多,大概举行RMAN块规复失败时,可以实验使用RMAN举行数据文件规复。
        使用RMAN举行数据文件规复会有几点事项必要注意:规复期间,数据库部分不可用,由于坏块所在的数据文件必要OFFLINE;必要确保归档日记完备以支持完全规复;假如坏块所在的数据文件比力大,规复服从不会很高。
  1. RMAN> VALIDATE BACKUPSET ALL; --查抄全部备份集是否可用,且有无坏块。RMAN> VALIDATE BACKUPSET <备份集编号>; --指定备份集举行查抄,查抄是否可用,且有无坏块。
复制代码
  1. RMAN> VALIDATE DATABASE; --检测坏块位置
复制代码
  1. SQL> ALTER DATABASE DATAFILE 4 OFFLINE; --离线坏块所在的数据文件
复制代码
  1. RMAN> RESTORE DATAFILE 4; --从备份恢复数据文件
复制代码
  1. RMAN> RECOVER DATAFILE 4; --还原坏块所在的数据文件
复制代码
  1. SQL> ALTER DATABASE DATAFILE 4 ONLINE; --切换数据文件为ONLINE状态。
复制代码
4.1.3、增补
        上文的备份集查抄是发起每次备份完就实验查抄,定期巡检也到场这类查抄。假如备份集不可用大概存在坏块,那么使用RMAN举行坏块修复的这条路就断掉了。
4.2、DBMS_REPAIR修复

        Oracle数据库提供了DBMS_REPAIR包用于修复坏块。但这个方法在修复坏块方面每每是不收效的。拟人化的讲,我个人以为这个DBMS包有点 “打的过就打,打不外就跑” 的感觉。由于它固然很多时间修不优劣块,但是它能让Oracle的增编削查使用跳过坏块;这也就导致了使用DBMS_REPAIR方法非常大概会丢失数据。但是在没有备份的环境下,这也是发生坏块时,能救济部分数据的方法之一。
        下图是DBMS_REPAIR的常用方法总结。

        如今Oracle数据库中HR.ZQD0318表有个坏块,接下来具体形貌下DBMS_REPAIR修复/跳过坏块的步调。
  1. SQL> SELECT COUNT(*) FROM HR.ZQD0318;
  2.   COUNT(*)
  3. ----------
  4.      72594
复制代码
4.2.1、创建REPAIR表
        REPAIR表用于记载必要被修复的表。REPAIR表创建完后,是不会立即有数据的;在查抄完对象的数据块受损环境后,REPAIR表才会有数据。
  1. BEGIN
  2. DBMS_REPAIR.ADMIN_TABLES(
  3.     TABLE_NAME => 'REPAIR_TABLE',
  4.     TABLE_TYPE => DBMS_REPAIR.REPAIR_TABLE,
  5.     ACTION => DBMS_REPAIR.CREATE_ACTION,
  6.     TABLESPACE => 'ZQD');
  7. END;
  8. --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码
4.2.2、 创建ORPHAN表
        ORPHAN表是用来存放在表出现坏块后的孤立(OPRHAN)索引相干信息,也就是指向那些坏块的索引信息。ORPHAN表创建完后,不会立即有数据;在使用DUMP_ORPHAN_KEYS过程后,才会有指向坏块的索引相干信息。
  1. BEGIN
  2.     DBMS_REPAIR.ADMIN_TABLES(
  3.     TABLE_NAME => 'ORPHAN_KEY_TABLE',
  4.     TABLE_TYPE => DBMS_REPAIR.ORPHAN_TABLE,
  5.     ACTION => DBMS_REPAIR.CREATE_ACTION,
  6.     TABLESPACE => 'ZQD');
  7. END;
  8. --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码
4.2.3、查抄对象的数据块受损环境
        查抄完后,坏块信息会写入REPAIR表。
  1. DECLARE
  2.     corruptnum INT;
  3. BEGIN
  4.     corruptnum := 0;
  5.     DBMS_REPAIR.CHECK_OBJECT(
  6.         SCHEMA_NAME => 'HR',
  7.         OBJECT_NAME => 'ZQD0318',
  8.         REPAIR_TABLE_NAME => 'REPAIR_TABLE',
  9.         CORRUPT_COUNT => corruptnum);
  10.     DBMS_OUTPUT.PUT_LINE('坏块数量:' || TO_CHAR(corruptnum));
  11. END;
  12. --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码
4.2.4、查察坏块信息
  1. SELECT OBJECT_NAME,BLOCK_ID,CORRUPT_TYPE,MARKED_CORRUPT,REPAIR_DESCRIPTION FROM REPAIR_TABLE;
复制代码

4.2.5、实验修复坏块
        假如输出是0,则阐明修复了0个坏块,修复无效,此时可以选择跳过坏块。
  1. DECLARE
  2. fixnum number;
  3. BEGIN
  4.     DBMS_REPAIR.FIX_CORRUPT_BLOCKS(
  5.         SCHEMA_NAME => 'HR',
  6.         OBJECT_NAME => 'ZQD0318',
  7.         FIX_COUNT => fixnum);
  8.     DBMS_OUTPUT.PUT_LINE('修复坏块的数量:' || TO_CHAR(fixnum));
  9. END;
  10. --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码
4.2.6、 记载指向坏块的索引相干信息
        实验完如下的PLSQL代码块后,失效索引相干信息(指向坏块的索引相干信息)会写入ORPHAN表。PLSQL代码块中的OBJECT_NAME是索引的名字,不是表名;假如有多个索引,必要为每个索引实验DUMP_ORPHAN_KEYS使用。
  1. DECLARE
  2.     DATAS NUMBER;
  3. BEGIN
  4.     DBMS_REPAIR.DUMP_ORPHAN_KEYS(
  5.         SCHEMA_NAME => 'HR',
  6.         OBJECT_NAME => 'IDX_ZQD',
  7.         OBJECT_TYPE => DBMS_REPAIR.INDEX_OBJECT,
  8.         REPAIR_TABLE_NAME => 'REPAIR_TABLE',
  9.         ORPHAN_TABLE_NAME => 'ORPHAN_KEY_TABLE',
  10.         KEY_COUNT => COUNTS);
  11.     DBMS_OUTPUT.PUT_LINE('孤立索引数量:' || TO_CHAR(COUNTS));
  12. END;
复制代码
4.2.7、跳过坏块
        实验下面PLSQL代码块后,坏块已被标志跳过。此时增编削查都不会报错,但坏块上的这部分数据也就丢失了。但丢失的数据的ROWID依然可以在ORPHAN表找到。
  1. BEGIN
  2.     DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(
  3.         SCHEMA_NAME => 'HR',
  4.         OBJECT_NAME => 'ZQD0318',
  5.         OBJECT_TYPE => DBMS_REPAIR.TABLE_OBJECT,
  6.         FLAGS => DBMS_REPAIR.SKIP_FLAG);
  7. END;
  8. --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码
4.2.8、重修索引
  1. ALTER INDEX HR.IDX_ZQD REBUILD
复制代码
4.2.9、验证结果
  1. SQL> SELECT COUNT(*) FROM HR.ZQD0318;
  2.   COUNT(*)
  3. ----------
  4.      72542
复制代码
4.2.10、后续
        上面的一套组合拳打完,表固然规复了访问、但是也丢失了部分数据。纵然丢失的数据可以通过其他方式补返来(比方数据堆栈可以再重新抽取数据),也存在一个标题:坏块依然存在。
        此时,将表中的数据全部导出(导出时跳过了坏块数据),然后重修表;再将导出的数据重新导入到数据库中;这个过程发起是使用数据泵expdp/impdp使用。使用完毕后,可以彻底消除坏块。
4.3、BBED

        BBED:Block Browser and Editor(块欣赏器和编辑器)
        BBED直接使用底层数据块,风险很高,必要非常专业的人士来使用。且使用不可逆,是作为坏块修复的末了一种本事使用。

5、写在末了

        上面简单先容了坏块的3种修复本事;但认真在生产上碰到了坏块环境,仅凭这篇文章的形貌,很难高效办理标题。这篇文章只是底子相识,想要高效办理坏块标题,除了底子以外,必要平常多做模仿演练,定期总结,才华在碰到坏块时,快速给出最完善的办理方案。

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表