Physical corruptions
介质坏块是指那些明显受到物理损坏的数据块,当oracle发现块头和块尾信息不一致、checksum值无效、数据块等信息全部为0等状况时,oracle会在读取块时报出ORA-01578、ORA-01110等异常,这些通常会写入到alert日志里。物理坏块通常是由于底层OS的问题引起,比如存储阵列缓存损坏、阵列固件损坏、文件系统错误等。所以oracle建议设置初始化参数DB_BLOCK_CHECKSUM=TYPICAL(默认值)
1 2 3 4 5
| SYS@xb> show parameter DB_BLOCK_CHECKSUM
NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_block_checksum string TYPICAL
|
模拟physical corruption场景
1 2 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日志里也能看到更详细的错误信息
1 2 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.trc Corrupt 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
1 2 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.out 1+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恢复
1 2 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
1 2 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
|