正常的数据块有其特有的固定格式,如果某数据块内部出现了混乱而导致Oracle无法读取,则可称其为坏块。数据库坏块的影响范围可大可小,严重时会导致数据库无法打开。当数据库出现坏块时,一般出现ORA-01578错误、ORA-10632错误或者ORA-00600错误。数据库产生坏块的原因主要有以下几种:
- ❑硬件问题。如内存混乱,CPU计算错误会导致内存中的数据块内容混乱,进而导致保存到磁盘后数据块损坏。
- ❑操作系统bug。Oracle的I/O写最终会由操作系统内核调用(system call)完成,当内核调用出现问题时,就可能产生坏块。
- ❑非Oracle进程异常修改Oracle SGA内存区域。如调用Linux或者UNIX操作系统的函数shmat非法attach到SGA中。
- ❑主机或者存储异常掉电。当掉电后存储的CACHE机制无法发挥正常作用时,极容易产生坏块。
- ❑Oracle bug。某些版本下的Oracle bug可能也会导致坏块产生,如bug 4493447。
1 数据库对象坏块的处理思路
业务对象上的坏块通常不会导致数据库宕机。假设数据库没有备份,数据库对象坏块的处理思路如下:
(1)可以使用dbv、RMAN、EXP/EXPDP或者VALIDATE命令校验数据库的坏块数量。建议使用dbv校验,因为RMAN、EXP/EXPDP或者VALIDATE校验坏块过程中可能会使数据库实例宕掉。此外EXP/EXPDP校验坏块时不会校验索引的坏块。
dba检测坏块输出:
--正常输出
[oracle@single ~]$ dbv
DBVERIFY: Release 11.2.0.4.0 - Production on Wed Dec 28 10:56:35 2022
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Keyword Description (Default)
----------------------------------------------------
FILE File to Verify (NONE)
START Start Block (First Block of File)
END End Block (Last Block of File)
BLOCKSIZE Logical Block Size (8192)
LOGFILE Output Log (NONE)
FEEDBACK Display Progress (0)
PARFILE Parameter File (NONE)
USERID Username/Password (NONE)
SEGMENT_ID Segment ID (tsn.relfile.block) (NONE)
HIGH_SCN Highest Block SCN To Verify (NONE)
(scn_wrap.scn_base OR scn)
[oracle@single ~]$
[oracle@single ~]$ dbv file=/data/app/oracle/oradata/orcl/testtbs.dbf
DBVERIFY: Release 11.2.0.4.0 - Production on Wed Dec 28 10:57:44 2022
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
DBVERIFY - Verification starting : FILE = /data/app/oracle/oradata/orcl/testtbs.dbf
DBVERIFY - Verification complete
Total Pages Examined : 182272
Total Pages Processed (Data) : 179936
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 935
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 1401
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Total Pages Encrypted : 0
Highest block SCN : 1505603 (0.1505603)
[oracle@single ~]$
--坏块输出:
[oracle@single ~]$ cat par.txt
1 /data/app/oracle/oradata/orcl/testtbs.dbf
[oracle@single ~]$ bbed password=blockedit listfile=/home/oracle/par.txt blocksize=8192 mode=edit
BBED: Release 2.0.0.0.0 - Limited Production on Wed Dec 28 11:11:39 2022
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
************* !!! For Oracle Internal Use only !!! ***************
BBED> info
File# Name Size(blks)
----- ---- ----------
1 /data/app/oracle/oradata/orcl/testtbs.dbf 0
BBED>
[oracle@single ~]$ cat par.txt
1 /data/app/oracle/oradata/orcl/testtbs.dbf
[oracle@single ~]$ bbed password=blockedit listfile=/home/oracle/par.txt blocksize=8192 mode=edit
BBED: Release 2.0.0.0.0 - Limited Production on Wed Dec 28 11:20:32 2022
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
************* !!! For Oracle Internal Use only !!! ***************
BBED>p kcvfh
BBED> set offset 368
BBED> modify /x 07
BBED> sum apply
[oracle@single ~]$ dbv file=/data/app/oracle/oradata/orcl/testtbs.dbf start=1 end=3
DBVERIFY: Release 11.2.0.4.0 - Production on Wed Dec 28 11:23:56 2022
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
DBVERIFY - Verification starting : FILE = /data/app/oracle/oradata/orcl/testtbs.dbf
Page 1 is marked corrupt
Corrupt block relative dba: 0x01c00001 (file 7, block 1)
Bad header found during dbv:
Data in bad block:
type: 11 format: 2 rdba: 0x00c00001
last change scn: 0x0000.00000000 seq: 0x1 flg: 0x04
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0x00000b01
check value in block header: 0xcdf6
computed block checksum: 0x0
Page 2 is marked corrupt
Corrupt block relative dba: 0x01c00002 (file 7, block 2)
Bad header found during dbv:
Data in bad block:
type: 29 format: 2 rdba: 0x00c00002
last change scn: 0x0000.0016f943 seq: 0x1 flg: 0x04
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0xf9431d01
check value in block header: 0x2ea6
computed block checksum: 0x0
Page 3 is marked corrupt
Corrupt block relative dba: 0x01c00003 (file 7, block 3)
Bad header found during dbv:
Data in bad block:
type: 30 format: 2 rdba: 0x00c00003
last change scn: 0x0000.0016f943 seq: 0x1 flg: 0x04
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0xf9431e01
check value in block header: 0x4048
computed block checksum: 0x0
DBVERIFY - Verification complete
Total Pages Examined : 3
Total Pages Processed (Data) : 0
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 0
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 0
Total Pages Marked Corrupt : 3
Total Pages Influx : 0
Total Pages Encrypted : 0
Highest block SCN : 0 (0.0)
[oracle@single ~]$
(2)如果索引出现坏块,则考虑删除并重建索引。索引有坏块时,一般不建议使用rebuild选项重建索引。
(3)如果表出现坏块,则设置10231事件或者使用dbms_repair包,从而在全表扫描时可以跳过坏块,也可以使用ROWID RANGE SCAN跳过坏块的数据。其使用方法可以参考MOS文章422547.1。
(4)使用bbed工具尝试修复坏块。需要注意的是,使用bbed修复坏块过程较为复杂且风险较大。
2 SYSTEM/UNDO表空间损坏的处理思路
SYSTEM/UNDO表空间损坏是比较棘手的故障,通常会导致数据库异常宕机进而无法打开数据库。数据库的打开故障处理起来相对比较麻烦,读者可以参考本书第5章进一步了解该类故障的处理过程。如果数据库没有备份,通常需要设置官方不推荐的隐含参数或者使用bbed工具修复损坏的数据块来强制打开数据库,所以此类故障处理起来存在着风险性和不可预知性。当碰到此类故障时,笔者的处理思路如下(假设数据库没有备份):
(1)检查数据库的警告日志,初步确定数据库打不开的原因。如果是RAC,则检查所有节点的警告日志。
(2)物理备份整个数据库。如果备份到本地磁盘,其备份速度最终取决于数据库大小和磁盘的I/O能力。如果通过网络备份到异地,那么其备份速度还取决于网络带宽。
(3)用dbv工具校验SYSTEM/UNDO表空间,确定数据块的损坏范围和严重程度。
(4)关闭监听。其目的是数据库成功打开之后,外部应用不会立刻连接至数据库。
(5)进行故障处理。具体的处理思路请参考第5章。
(6)如果是UNDO表空间有坏块,可以设置隐含参数_offline_rollback_segments屏蔽坏块所在的回滚段来打开数据库。如果熟悉数据块格式,则可以用bbed工具修复损坏的数据块。
提示 如果空间不够或者整个数据库备份时间过长,则依然需要备份SYSTEM、UNDO和SYSAUX表空间下的数据文件、控制文件、所有在线日志文件。非常规手段修复数据库所带来的副作用很难被DBA全部预见到,为防止事态进一步恶化,在处理问题之前必须全部备份上述文件。对于不可逆转的修复,DBA一定要小心,做好备份工作!
3 数据库在线日志文件损坏的处理思路
千万不要在数据库运行时,突然关闭主机或者存储,由于在线日志的写操作非常频繁,所以主机或者存储异常宕机之后,在线日志往往会损坏。在线日志损坏也就意味着丢失数据,数据库就无法正常打开,所以需要引起读者足够的重视。当碰到此类故障时,笔者的处理思路如下:
(1)如果损坏的是INACTIVE状态的在线日志,则启动数据库至MOUNT状态,然后使用CLEAR LOGFILE命令重新生成该日志文件,这样就可以正常打开数据库。在CLEAR LOGFILE过程中,服务器进程会根据记录在控制文件的日志文件的大小重新格式化日志块,所以刚生成的日志文件块除了块头信息,没有其他任何内容。
(2)如果损坏的是ACTIVE或者CURRENT状态的在线日志,则设置隐含参数_allow_resetlogs_corruption为TRUE,然后进行不完全恢复,并使用RESETLOGS模式强制打开数据库。
(3)在强制打开数据库的过程中,如果出现ORA-00600[2662]错误,则可以使用10015事件或者隐含参数_minimum_giga_scn递增全库SCN值。




