一、基本知识总结
1. 介质损坏(media corrupt)与逻辑损坏(logically corrupt)
所谓“块损坏”指块没有采用可识别的Oracle 格式,或者其内容在内部不一致。通常情况下,损坏是由硬件故障或操作系统问题引起的,包括介质损坏和块损坏。Oracle 数据库将损坏的块标识为“逻辑损坏”或“介质损坏”。
介质损坏:Oracle服务器根本无法识别此块,校验和无效,块的内容全部为零,或者块头和块尾不匹配。通常由硬件引起,需要通过修复硬件来彻底解决问题。此时应运行一次全面的硬件诊断会话,来确定出错的位置。
逻辑损坏:块的校验和有效,块头和块尾也匹配,但是内容在逻辑上不一致。通常是由Oracle内部错误引发的,数据库检测到不一致后,会将逻辑损坏的块标记为损坏(表和索引逻辑验证的详细介绍,参看analyze....validate structure)。
当损坏发生时,系统将在alert.log中写入一个ORA-01578和ORA-01110错误。:ORA-01578 会返回相对文件号,随之出现的ORA-01110 错误会显示绝对文件号。
ORA-01578: Oracle data block corrupted (file # 4, block $ 11)
ORA_01110: data file 4: '/db/oradata/study/user01.dbf'
2. 逻辑验证和物理验证工具
发现有数据块坏,我们就需要使用工具来对数据文件进行扫描,定位到发生损坏的数据块的位置。暴露出来的数据块坏可能只是冰山一角,也可能昙花一现,所以为了定位准确,需要多次扫描,仔细确定出错的位置和性质,再决定解决问题的方案。
DBV | 检查块的一致性 | 物理验证 |
analyze ...validate structure | 分析对象的逻辑结构 | 逻辑验证 |
DB_BLOCK_CHECKING | 通过读取块中的数据,执行自我一致性检查 | 逻辑验证 |
DB_BLOCK_CHECKSUM | 在写入磁盘前计算校验,将其记录到块高速缓冲头中。读取前,重新计算校验,确定无物理损坏。 | 物理验证 |
EXP / EXPDP | 常规导出检测损坏 | 物理验证 |
Flashback | 通过闪回查询确定发生逻辑损坏的时间。运用闪回还原数据损坏。 | 逻辑验证 |
DBMS_REPAIR | 检测并修复表和索引中损坏的块 | 逻辑验证 |
BMR (BlockRecover) | RMAN从备份集中还原个别数据块。 |
所谓的逻辑验证主要是分析对象的逻辑结构是否完整,类似于执行analyze...validate structure的操作;而物理验证则在读取数据块时计算校验码,然后与块高速缓存中的进行比较,判断其一致性。如果不一致,系统会报ORA-01578错误。
将上述工具强行分为逻辑验证还是物理验证,我觉得没有必要。例如:select * from table_name这样的全表扫描,也可以进行物理验证。只要发生了checksum一类的校验活动,发现其中可能存在的损坏都可以属于物理验证的范围。而逻辑验证,我认为主要是在频繁发生插入、删除操作后的索引与数据表间存在着差异,以及进行分区操作后的分区表、进行聚类操作的聚类表等比较复杂的数据块组织结构中,可能发生的逻辑结构方面的问题。逻辑问题一般是由软件操作引发的,通过修复可以一次性解决;介质问题则必须先进行硬件修复,否则即便把数据找回来了,也可能再次发生丢失。
对于索引,直接通过重建对象来解决;对于数据库错误,如果系统运行在archive模式下,那么运用BMR技术来进行块级别的恢复是最佳的选择;如果损坏的块没有找到相应的备份,那么将损失降到最低限度是唯一的选择。
在损坏的块无法重建的情况下,如果问题发生的时间不长,丢失的数据可以在undo中找到的话,可以使用flashback来找回信息;如果丢失的数据块所在表对应的索引尚在,那么通过DBMS_REPAIR定位到出错的数据块,然后将其标识为不可用,从而继续使用这些对象。
3. DBV
l 主要用户对备份文件物理完整性进行检验,但不能进行修复。
l DBV仅能检查文件,不能检查其中包含的对象;
l DBV不能验证在线重做日志文件和控制文件的块错误;
4. analyze....validate structure
资料来源:Oracle102server.102b14200statements_4005.htm#i2086320
对于堆表,Oracle将验证每一个数据块和记录的完整性。
对于IOT,数据库将为表中主键生成一个压缩统计。
对于Cluster,Oracle将自动验证群集表的结构。
对于分区表,数据库同样验证每一行是否属于正确的分区。如果某行没有正确的分配,那么他的rowid将插入到INVALID_ROWS表中。
SYS@ db1>@?/rdbms/admin/utlvalid.sql;
表已创建。
SYS@ db1>create public synonym invalid_rows for invalid_rows;
同义词已创建。
SYS@ db1>grant insert, select on invalid_rows to public;
授权成功。
SYS@ db1>analyze table scott.emp validate structure into invalid_rows;
analyze table scott.emp validate structure into invalid_rows;
第 1 行出现错误:
ORA-14510: 只能为分区表指定 VALIDATE INTO 子句
对于临时表,Oracle将验证它在当前会话中的表和索引的结构。
对于索引,数据库验证其中每一个数据块的完整性,并检查可能存在的块冲突。系统分析的结果,可以在XXX_Indexes、Index_stats、Index_Histogram数据字典视图中找到。
SYS@ db1>analyze index pk_emp validate structure; --单独验证索引的逻辑完整性。
SYS@ db1>analyze table emp validate structure cascade; --级联验证与emp相关的索引的逻辑完整性。
此外,如果用户需要分析其他schema中的对象,需要analyze any权限。
analyze的功能还是有很大局限性的,每条命令只能影响到一个table。如果想对整个schema进行验证分析,建议使用dbms_utility(Oracle8i之前)软件包;进行统计分析,则dbms_stats(Oracle8i之后)软件包功能更加强大。
5. DB_BLOCK_CHECKING系统参数
通过设定该参数,系统自动进行块逻辑完整性扫描,即系统自动在后台执行analyze....validate structure的操作。
系统执行插入、删除的次数越多,系统执行块检查的开销越高。系统将依据参数设定的级别来决定analyze操作的对象范围。
FULL > MEDIUM > LOW > OFF(FALSE)
l OFF仅检查SYSTEM表空间中的对象;
l LOW增加内存中发生改变的块;
l MEDIUM增加数据表(除IOT之外,因为其数据存放在索引段中)的检查
l FULL增加对索引块的检查
因为此操作比较耗CPU,默认系统设定为关闭。即使关闭了此选项,也始终对SYSTEM 表空间执行块检查。
DB_BLOCK_CHECKING=OFF
6. DBMS_REPAIR软件包
使用DBMS_REPAIR软件包,尝试通过从索引中检索数据来修复损坏的数据块。整个修复的基本过程是:
l 通过admin_tables过程建立一个repair_table来记录对象损坏的状况和修复指令的信息,建立orphan_key_table来存放指向损坏数据块中的行的索引条目。
l 调用check_object来检测坏块,调用fix_corrupt_blocks将坏块存放到repair_table中。
l 调用dump_orphan_keys来保持坏块中的索引键值(即孤键),将其存放到orphan_key_table中。
l 如果该表空间采用手工管理的方式,那么需要调用rebuild_freelists来修改freelists。(通过freelists来记录空块的技术,在系统采用ASSM进行段管理后不再有用)。
l 执行skip_corruption_blocks,使后续的DML操作跳过坏块。
任何工具都不是万能的,使用这个包的同时会带来数据丢失、表和索引返回数据不一致,完整性约束破坏等其他问题。因此当出现错误时,应当首先从物理备份或逻辑备份恢复,使用dbms_repair只是在没有备份的情况下使用的一种手段,这种方式一般都会造成数据的丢失。
7. 使用RMAN的块介质恢复(BMR)
BMR 将介质恢复的最小可恢复单位从数据文件缩小到块,可以降低MTTR,并在恢复的过程中将数据文件继续保持在联机状态。BMR运用redo流(在线重做日志和归档重做日志)从相应的备份中还原个别数据块。
BMR恢复的过程很简单,难点在如何定位所需恢复的数据块的位置。当系统报ORA-01578错误时,仅仅表示指定的块存在错误。但错误往往会发生扩散,或者存在不确定性,例如某些硬件引发的块错误并不稳定。所以需要多次对数据文件进行扫描,查找可能存在的错误的位置。定位出错数据块的方法如下:
l 通过DBV扫描确定:
Corrupt表明当前块为介质损坏;influx表明当前块第一次读首尾不匹配,重读后匹配。引发influx的原因未必是数据块坏,当数据库正处于打开状态,DBV将对数据块进行多次读取操作,多次读取的结果可能存在不同。
Influx: number of blocks that are being read and written to at the same time. If the database is open when DBVERIFY is run, DBVERIFY reads blocks multiple times to get a consistent image. But because the database is open, there may be blocks that are being read and written to at the same time (INFLUX).
资料来源:/oracle102/server.102/b14215/dbverify.htm#sthref1837
下面是一个DBV扫描的错误块,Oracle根本无法识别此块,校验和无效,块的内容全部为零(Data in bad block)。dba: 0x00000267指明坏块的地址(database address),地址为16进制。file 0, block 615指明坏块的相对位置。这两个都可以作为blockrecover进行恢复的依据。
Page 615 is influx - most likely media corrupt
Corrupt block relative dba: 0x0040006C (file 1, block 615)
Fractured block found during dbv:
Data in bad block:
type: 0 format: 0 rdba: 0x00000000
last change scn: 0x0000.00000000 seq: 0x0 flg: 0x00
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0x00000000
check value in block header: 0x0
block checksum disabled
通过DBV的提示信息,可以在RMAN中执行进行修复。
RMAN> BLOCKRECOVER DATAFILE 1 BLOCK 615
或者
RMAN> BLOCKRECOVER TABLESPACE users DBA 4194405
l RMAN验证
在备份和复制过程中,如果增加validate子句,RMAN会进行块的校验。
RMAN> backup validate tablespace users;
RMAN> backup as copy validate tablespace users;
校验的结果在以下视图中得到体现。
V$Database_Block_Corruption
V$Backup_Corruption
V$Copy_Corruption
RMAN可以通过使用CORRUPTION LIST 子句,可以恢复V$DATABASE_BLOCK_CORRUPTION 中列出的块。
RMAN> BLOCKRECOVER CORRUPTION LIST;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/20162/viewspace-1034186/ ,如需转载,请注明出处,否则将追究法律责任。