Oracle物理坏块(corruption)

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

Oracle物理坏块(corruption)
https://www.xbdba.com/2018/10/27/oracle-physical-block-corruption/
作者
xbdba
发布于
2018年10月27日
许可协议