Physical corruptions
介质坏块是指那些明显受到物理损坏的数据块,当oracle发现块头和块尾信息不一致、checksum值无效、数据块等信息全部为0等状况时,oracle会在读取块时报出ORA-01578、ORA-01110等异常,这些通常会写入到alert日志里。物理坏块通常是由于底层OS的问题引起,比如存储阵列缓存损坏、阵列固件损坏、文件系统错误等。所以oracle建议设置初始化参数DB_BLOCK_CHECKSUM=TYPICAL(默认值)
| 12
 3
 4
 5
 
 | SYS@xb> show parameter DB_BLOCK_CHECKSUM
 NAME                     TYPE    VALUE
 ------------------------------------ ----------- ------------------------------
 db_block_checksum            string  TYPICAL
 
 | 
模拟physical corruption场景
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 
 | SYS@xb> create tablespace tbsxb datafile '/u01/app/oracle/oradata/xb/tbsxb01.dbf' size 100m;
 表空间已创建。
 
 SYS@xb> create table xb_corrupt tablespace tbsxb as select * from dba_tables;
 
 表已创建。
 
 SYS@xb> select dbms_rowid.rowid_block_number(rowid),dbms_rowid.rowid_relative_fno(rowid) from xb_corrupt where rownum>10;
 
 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID)
 ------------------------------------ ------------------------------------
 131                    5
 131                    5
 131                    5
 131                    5
 131                    5
 131                    5
 131                    5
 131                    5
 131                    5
 
 已选择9行。
 
 SYS@xb> alter system checkpoint;
 
 系统已更改。
 
 SYS@xb> quit
 
 RMAN> recover datafile 5 block 131 clear;
 
 启动 recover 于 23-10月-18
 使用目标数据库控制文件替代恢复目录
 分配的通道: ORA_DISK_1
 通道 ORA_DISK_1: SID=42 设备类型=DISK
 完成 recover 于 23-10月-18
 
 SYS@xb> alter system flush buffer_cache;
 
 系统已更改。
 
 SYS@xb> select count(1) from xb_corrupt;
 select count(1) from xb_corrupt
 *
 第 1 行出现错误:
 ORA-01578: ORACLE 数据块损坏 (文件号 5, 块号 131)
 ORA-01110: 数据文件 5: '/u01/app/oracle/oradata/xb/tbsxb01.dbf'
 
 | 
可以看到现在查询表的时候出现了坏块提示,坏块为file# 5, block# 131,同时在alert日志里也能看到更详细的错误信息
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 
 | Hex dump of (file 5, block 131) in trace file /u01/app/oracle/diag/rdbms/xb/xb/trace/xb_ora_29669.trcCorrupt block relative dba: 0x01400083 (file 5, block 131)
 Bad check value found during multiblock buffer read                              >>>>====这里说明错误块的原因是checksum值无效
 Data in bad block:
 type: 6 format: 2 rdba: 0x01400083
 last change scn: 0x0000.0013d894 seq: 0x2 flg: 0x04
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0xd8940602
 check value in block header: 0xb5ad                                            >>>>====数据块中记录的checksum值为0xb5ad
 computed block checksum: 0x3494                                                >>>>====做完异或运算后得到的差值为0x3494
 Reading datafile '/u01/app/oracle/oradata/xb/tbsxb01.dbf' for corruption at rdba: 0x01400083 (file 5, block 131)
 Reread (file 5, block 131) found same corrupt data (no logical check)
 Tue Oct 23 14:48:44 2018
 Corrupt Block Found
 TSN = 9, TSNAME = TBSXB
 RFN = 5, BLK = 131, RDBA = 20971651
 OBJN = 87870, OBJD = 87870, OBJECT = XB_CORRUPT, SUBOBJECT =
 SEGMENT OWNER = SYS, SEGMENT TYPE = Table Segment                       >>>>====坏块所在的对象信息
 Corrupt Block Found
 TSN = 9, TSNAME = TBSXB
 RFN = 5, BLK = 131, RDBA = 20971651
 OBJN = 87870, OBJD = 87870, OBJECT = XB_CORRUPT, SUBOBJECT =
 SEGMENT OWNER = SYS, SEGMENT TYPE = Table Segment
 Errors in file /u01/app/oracle/diag/rdbms/xb/xb/trace/xb_ora_29669.trc  (incident=84945):
 ORA-01578: ORACLE 数据块损坏 (文件号 5, 块号 131)
 ORA-01110: 数据文件 5: '/u01/app/oracle/oradata/xb/tbsxb01.dbf'
 Incident details in: /u01/app/oracle/diag/rdbms/xb/xb/incident/incdir_84945/xb_ora_29669_i84945.trc
 Errors in file /u01/app/oracle/diag/rdbms/xb/xb/trace/xb_ora_29669.trc  (incident=84946):
 ORA-01578: ORACLE 数据块损坏 (文件号 5, 块号 131)
 ORA-01110: 数据文件 5: '/u01/app/oracle/oradata/xb/tbsxb01.dbf'
 Incident details in: /u01/app/oracle/diag/rdbms/xb/xb/incident/incdir_84946/xb_ora_29669_i84946.trc
 Tue Oct 23 14:48:46 2018
 Sweep [inc][84945]: completed
 
 | 
这些错误信息说明错误原因为checksum值无效,第一次DBWR写入磁盘时记录的checksum值为0xb5ad,而重新读取的时候计算的checksum与之前的值做完异或运算后得到0x3494,由于两次结果的异或值为非0,则oracle会标记这个块为坏块
CHECKSUM的相关介绍可以看我的另一篇博客Oracle Block Checksum
通过dd也查看数据块中记录的checksum值, offset 16,17
| 12
 3
 4
 5
 6
 7
 8
 
 | [root@xb ~]# dd if=/u01/app/oracle/oradata/xb/tbsxb01.dbf bs=8192 count=1 skip=131 of=/tmp/131.out1+0 records in
 1+0 records out
 8192 bytes (8.2 kB) copied, 4.8438e-05 s, 169 MB/s
 [root@xb ~]# vim /tmp/131.out
 [root@xb ~]# od -x /tmp/131.out
 0000000 a206 0000 0083 0140 d894 0013 0000 0402
 0000020 b5ad 0000 0001 0000 573e 0001 d884 0013
 
 | 
修复坏块
可以通过备份恢复或者包DBMS_REPAIR.SKIP_CORRUPT_BLOCKS来跳过坏块后导出
rman恢复
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | RMAN> blockrecover datafile 5 block 131;
 启动 recover 于 23-10月-18
 使用通道 ORA_DISK_1
 
 通道 ORA_DISK_1: 正在还原块
 通道 ORA_DISK_1: 正在指定要从备份集还原的块
 正在还原数据文件 00005 的块
 通道 ORA_DISK_1: 正在读取备份片段 /u01/app/oracle/fast_recovery_area/XB/backupset/2018_10_23/o1_mf_nnndf_TAG20181023T155016_fwxnorhl_.bkp
 通道 ORA_DISK_1: 段句柄 = /u01/app/oracle/fast_recovery_area/XB/backupset/2018_10_23/o1_mf_nnndf_TAG20181023T155016_fwxnorhl_.bkp 标记 = TAG20181023T155016
 通道 ORA_DISK_1: 已从备份片段 1 还原块
 通道 ORA_DISK_1: 块还原完成, 用时: 00:00:01
 
 正在开始介质的恢复
 介质恢复完成, 用时: 00:00:01
 
 完成 recover 于 23-10月-18
 
 | 
DBMS_REPAIR.SKIP_CORRUPT_BLOCKS
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | SYS@xb> alter session set db_file_multiblock_read_count=1;
 会话已更改。
 
 SYS@xb> execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('SYS','XB_CORRUPT');
 
 PL/SQL 过程已成功完成。
 
 SYS@xb> create table xb_corrupt_new as select * from xb_corrupt;
 
 表已创建。
 
 SYS@xb> select count(1) from xb_corrupt_new;
 
 COUNT(1)
 ----------
 2780
 
 |