马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
目次
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来查察当前数据库对于此参数的设置环境。
- SQL> show parameter db_block_checksum
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
- db_block_checksum string TYPICAL
复制代码 db_block_checksum参数有3种选项:FULL、TYPICAL、OFF,下面临这三种选项举行简单阐明。
| 参数选项 | 简单阐明 | | FULL | 对全部数据块,包罗数据文件、控制文件、日记文件天生校验和。 | | TYPICAL | 默认值,对数据文件、控制文件天生校验和,不会作用于临时表空间。 | | OFF | 不天生checksum,这个是不保举的。 | 可以修改db_block_checksum参数,但由于是静态参数,修改完参数必要重启数据库。
- 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参数,但由于是静态参数,修改完参数必要重启数据库。
- 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在检测到数据坏块时,会在告警日记中记载错误信息。通过查抄告警日记,可以实时发现数据坏块错误。
确定告警日记位置,以下两个方法都可以。
- SQL> show parameter dump
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
- background_core_dump string partial
- background_dump_dest string /oracle/app/diag/rdbms/htbase/htbase1/trace
- core_dump_dest string /oracle/app/diag/rdbms/htbase/htbase1/cdump
- max_dump_file_size string unlimited
- shadow_core_dump string PARTIAL
- user_dump_dest string /oracle/app/diag/rdbms/htbase/htbase1/trace
- SQL> SELECT value FROM v$diag_info WHERE name = 'Diag Trace';
- VALUE
- --------------------------------------------------------------------------------
- /oracle/app/diag/rdbms/htbase/htbase1/trace
复制代码 检索坏块错误记载
在告警日记中搜索“ORA-01578”,大概搜素“Corrupt block“关键字。这个各人可以看上文物理坏块先容那边就知道为什么检索两个了。
3.2、RMAN
RMAN也是官方保举坏块检测工具,支持对数据文件、控制文件、归档日记文件等举行完备性查抄,个人以为RMAN比力适看成为一种定期康健查抄的本事。RMAN有下面几种查抄方式。
3.2.1、查抄整个数据库
可以输出全部数据文件、控制文件、日记文件的坏块信息。
3.2.2、查抄指定的数据文件
可以输出数据文件内每个块的物理和逻辑划一性。
- RMAN> VALIDATE DATAFILE 28; -- 文件号为28的数据文件
复制代码 3.2.3、逻辑划一性查抄
不光查抄数据块的物理完备性,还会查抄数据块的逻辑结构。
- RMAN> VALIDATE CHECK LOGICAL DATABASE;
复制代码 3.2.4、查抄备份集
这个下令,无论是新手还是老手都不陌生,备份常用下令,查抄备份文件是否破坏,确保规复的时间是可用的。
- RMAN> VALIDATE BACKUPSET <备份集编号>;
复制代码 3.3、ANALYZE
ANALYZE下令可以查抄表、索引的逻辑划一性。
3.3.1、查抄表结构
假如存在坏块,会抛出ORA-01498错误。此时大概是数据块头部的元数据信息堕落、索引对应数据块的关联关系有误(这些都在上文的逻辑坏块部分先容过);假如是物理坏块,还会伴随着ORA-01578。
- ANALYZE TABLE hr.zqd VALIDATE STRUCTURE;
复制代码 3.3.2、查抄索引的划一性
假如索引与表数据不匹配,会抛出ORA-01499错误。这大概是索引和表数据没同步,比方删除大量数据后,没有重修索引;事件非常制止导致索引条目没有正常更新等等。假如是物理破坏的话,会伴随着ORA-01578错误。
此时比力高效的修复使用是重修索引,但不肯定能办理全部场景下的此类标题。
- ANALYZE INDEX HR.zqd_idx VALIDATE STRUCTURE;
复制代码 3.4、数据字典
3.4.1、V$DATABASE_BLOCK_CORRUPTION
- 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体系底子表,可以定位到具体的坏块所在对象,大概是表、索引、大字段。
- SELECT owner, segment_name, segment_type
- FROM dba_extents
- WHERE file_id = 5 -- 文件号
- 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文件。
- 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
- dbv FILE=/oradata/users01.dbf BLOCKSIZE=8192 LOGFILE=/tmp/dbv.log
复制代码 4、修复坏块
4.1、RMAN修复
最抱负的是使用RMAN规复,进而实现修复坏块的目的。但这是必要当前数据库有备份,而且备份可用无坏块的环境下。
4.1.1、使用RMAN举行块规复
检测到数据库的坏块、坏块所在数据文件后,可以指定坏块举行块规复。发起是在数据库坏块不多的环境下使用块规复,这种修复服从很高;假如是规复整个数据文件,规复服从会相对很低。
- RMAN> VALIDATE BACKUPSET ALL; --查抄全部备份集是否可用,且有无坏块。RMAN> VALIDATE BACKUPSET <备份集编号>; --指定备份集举行查抄,查抄是否可用,且有无坏块。
复制代码- RMAN> VALIDATE DATABASE; --检测坏块位置
复制代码- RMAN> blockrecover datafile 4 block 1798; --进行块恢复
- --也可以一次修复同一数据文件中的多个坏块
- RMAN> blockrecover datafile 4 block 1798,1799; --进行多个坏块恢复
复制代码- VALIDATE DATAFILE 4 BLOCK 1798; --验证修复结果
复制代码 4.1.2、使用RMAN举行数据文件规复
假如数据库中的坏块很多,大概举行RMAN块规复失败时,可以实验使用RMAN举行数据文件规复。
使用RMAN举行数据文件规复会有几点事项必要注意:规复期间,数据库部分不可用,由于坏块所在的数据文件必要OFFLINE;必要确保归档日记完备以支持完全规复;假如坏块所在的数据文件比力大,规复服从不会很高。
- RMAN> VALIDATE BACKUPSET ALL; --查抄全部备份集是否可用,且有无坏块。RMAN> VALIDATE BACKUPSET <备份集编号>; --指定备份集举行查抄,查抄是否可用,且有无坏块。
复制代码- RMAN> VALIDATE DATABASE; --检测坏块位置
复制代码- SQL> ALTER DATABASE DATAFILE 4 OFFLINE; --离线坏块所在的数据文件
复制代码- RMAN> RESTORE DATAFILE 4; --从备份恢复数据文件
复制代码- RMAN> RECOVER DATAFILE 4; --还原坏块所在的数据文件
复制代码- 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修复/跳过坏块的步调。
- SQL> SELECT COUNT(*) FROM HR.ZQD0318;
- COUNT(*)
- ----------
- 72594
复制代码 4.2.1、创建REPAIR表
REPAIR表用于记载必要被修复的表。REPAIR表创建完后,是不会立即有数据的;在查抄完对象的数据块受损环境后,REPAIR表才会有数据。
- BEGIN
- DBMS_REPAIR.ADMIN_TABLES(
- TABLE_NAME => 'REPAIR_TABLE',
- TABLE_TYPE => DBMS_REPAIR.REPAIR_TABLE,
- ACTION => DBMS_REPAIR.CREATE_ACTION,
- TABLESPACE => 'ZQD');
- END;
- --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码 4.2.2、 创建ORPHAN表
ORPHAN表是用来存放在表出现坏块后的孤立(OPRHAN)索引相干信息,也就是指向那些坏块的索引信息。ORPHAN表创建完后,不会立即有数据;在使用DUMP_ORPHAN_KEYS过程后,才会有指向坏块的索引相干信息。
- BEGIN
- DBMS_REPAIR.ADMIN_TABLES(
- TABLE_NAME => 'ORPHAN_KEY_TABLE',
- TABLE_TYPE => DBMS_REPAIR.ORPHAN_TABLE,
- ACTION => DBMS_REPAIR.CREATE_ACTION,
- TABLESPACE => 'ZQD');
- END;
- --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码 4.2.3、查抄对象的数据块受损环境
查抄完后,坏块信息会写入REPAIR表。
- DECLARE
- corruptnum INT;
- BEGIN
- corruptnum := 0;
- DBMS_REPAIR.CHECK_OBJECT(
- SCHEMA_NAME => 'HR',
- OBJECT_NAME => 'ZQD0318',
- REPAIR_TABLE_NAME => 'REPAIR_TABLE',
- CORRUPT_COUNT => corruptnum);
- DBMS_OUTPUT.PUT_LINE('坏块数量:' || TO_CHAR(corruptnum));
- END;
- --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码 4.2.4、查察坏块信息
- SELECT OBJECT_NAME,BLOCK_ID,CORRUPT_TYPE,MARKED_CORRUPT,REPAIR_DESCRIPTION FROM REPAIR_TABLE;
复制代码
4.2.5、实验修复坏块
假如输出是0,则阐明修复了0个坏块,修复无效,此时可以选择跳过坏块。
- DECLARE
- fixnum number;
- BEGIN
- DBMS_REPAIR.FIX_CORRUPT_BLOCKS(
- SCHEMA_NAME => 'HR',
- OBJECT_NAME => 'ZQD0318',
- FIX_COUNT => fixnum);
- DBMS_OUTPUT.PUT_LINE('修复坏块的数量:' || TO_CHAR(fixnum));
- END;
- --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码 4.2.6、 记载指向坏块的索引相干信息
实验完如下的PLSQL代码块后,失效索引相干信息(指向坏块的索引相干信息)会写入ORPHAN表。PLSQL代码块中的OBJECT_NAME是索引的名字,不是表名;假如有多个索引,必要为每个索引实验DUMP_ORPHAN_KEYS使用。
- DECLARE
- DATAS NUMBER;
- BEGIN
- DBMS_REPAIR.DUMP_ORPHAN_KEYS(
- SCHEMA_NAME => 'HR',
- OBJECT_NAME => 'IDX_ZQD',
- OBJECT_TYPE => DBMS_REPAIR.INDEX_OBJECT,
- REPAIR_TABLE_NAME => 'REPAIR_TABLE',
- ORPHAN_TABLE_NAME => 'ORPHAN_KEY_TABLE',
- KEY_COUNT => COUNTS);
- DBMS_OUTPUT.PUT_LINE('孤立索引数量:' || TO_CHAR(COUNTS));
- END;
复制代码 4.2.7、跳过坏块
实验下面PLSQL代码块后,坏块已被标志跳过。此时增编削查都不会报错,但坏块上的这部分数据也就丢失了。但丢失的数据的ROWID依然可以在ORPHAN表找到。
- BEGIN
- DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(
- SCHEMA_NAME => 'HR',
- OBJECT_NAME => 'ZQD0318',
- OBJECT_TYPE => DBMS_REPAIR.TABLE_OBJECT,
- FLAGS => DBMS_REPAIR.SKIP_FLAG);
- END;
- --如果在SQLPLUS中执行PLSQL代码块,需要在代码块末尾加上“/”
复制代码 4.2.8、重修索引
- ALTER INDEX HR.IDX_ZQD REBUILD
复制代码 4.2.9、验证结果
- SQL> SELECT COUNT(*) FROM HR.ZQD0318;
- COUNT(*)
- ----------
- 72542
复制代码 4.2.10、后续
上面的一套组合拳打完,表固然规复了访问、但是也丢失了部分数据。纵然丢失的数据可以通过其他方式补返来(比方数据堆栈可以再重新抽取数据),也存在一个标题:坏块依然存在。
此时,将表中的数据全部导出(导出时跳过了坏块数据),然后重修表;再将导出的数据重新导入到数据库中;这个过程发起是使用数据泵expdp/impdp使用。使用完毕后,可以彻底消除坏块。
4.3、BBED
BBED:Block Browser and Editor(块欣赏器和编辑器)
BBED直接使用底层数据块,风险很高,必要非常专业的人士来使用。且使用不可逆,是作为坏块修复的末了一种本事使用。
5、写在末了
上面简单先容了坏块的3种修复本事;但认真在生产上碰到了坏块环境,仅凭这篇文章的形貌,很难高效办理标题。这篇文章只是底子相识,想要高效办理坏块标题,除了底子以外,必要平常多做模仿演练,定期总结,才华在碰到坏块时,快速给出最完善的办理方案。
|