a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 132|回复: 2

[考试辅导] Oracle数据库中的坏块的技术

[复制链接]
发表于 2012-8-4 14:06:19 | 显示全部楼层 |阅读模式
数据库的数据块有固定的格式和结构,分三层:cache layer,transaction layer,data layer。在我们对数据块进行读取写入操作的时候,数据库会对要读写的数据块做一致性的检查,其中包括:数据块的类型、数据块的地址信息、数据块的SCN号以及数据块的头部和尾部。如果发现其中有不一致的信息,那数据库就会标记这个数据块为坏块了。数据库的坏块分为两种,逻辑坏块和物理坏块。   
) r8 Z$ H! f& q% g4 }4 q1 ~1 J* k! h0 q1 l: L( Q% U' i5 a
  坏块对数据库产生的影响:   2 n6 C$ K8 [& {
) E4 g" U# O0 x- @% m. F6 L, L
  如果数据库出现坏块,数据库的告警日志文件里面会存在有如下的一些报错信息:Ora-1578以及Ora-600 and trace file in bdump directory,其中Ora-600错误的第一个参数值的范围是[2000]-[8000],不同的值代表着数据块的不同的层出现问题,参照下表:   
1 {. v) I8 U" @! F4 l* q8 v9 |4 D# _
# o- O- c# U4 m: h# o  t, iRange block layer  
! a, b' l$ q0 r& n9 W1 YCache layer 2000 – 4000  3 `" c, q/ d+ k. [/ c
Transaction layer 4000 – 6000  / x$ ~* `. E+ G6 c! M: N; [. P
Data layer 6000 - 8000  
; b! `7 Y0 x- C+ e# h7 l' q
7 W  q$ L' W; o- v' `  坏块产生影响的对象可能是数据字典表、回滚段表、临时段、用户数据表和索引等。不同的对象产生坏块后的处理方法不尽相同。   ' k6 \" a4 ^8 w- A% Z# @

* ?8 A4 O; f% s8 ~% a  三:坏块产生的原因   
4 E% l; g, z/ t
$ w6 l" ^6 [5 c+ v, b+ Y  Oracle调用标准C的系统函数,对数据块进行读写操作,因此,坏块是有可能由以下几种原因产生:   
* r5 J2 j1 H2 y2 ]& [2 Z; D6 q
+ O; f% X' T- F  硬件的I/O错误   % g1 p: n# s0 H5 W) o
  操作系统的I/O错误或缓冲问题   
; x% h5 k7 M# `7 |8 n6 O8 o  内存或paging问题   
8 }; `2 |' |0 s: o% J" C1 P# x0 V  磁盘修复工具   - k+ B( ]9 g+ T; ~! ~1 s
  一个数据文件的一部分正在被覆盖   1 X- y' S1 f1 S
  Oracle试图访问一个未被格式化的系统块失败   ! b# u" l9 K: b! @  \
  数据文件部分溢出   $ b2 D; `" ~' H
  Oracle或者操作系统的bug   % b; h0 q7 U$ ^2 S! a! N2 j4 g+ t

0 s$ ?# _/ C1 q; J1 P/ r" C4 K  坏块的处理方法   
, X; H7 F4 E  B' ]$ t7 O  1. 先收集相应的关于坏快的信息,从AlertSID.log文件或者从trace文件中查找,找到例如以下的一些信息:   
& }. O0 W& G- j/ J' d" A, C
) Y& v9 R$ m+ ^8 r$ @' y5 d$ POra-1578 file# (RFN) block#    L$ v1 J* r& Q- L" }6 _7 J
Ora-1110 file# (AFN) block#  
$ k( M( b9 p- D$ POra-600 file# (AFN) block#   * J3 i7 G1 E4 [- [. U! B3 X1 P: [
其中RFN表示的是relative_fno   8 C0 m/ I+ }0 k5 M( g% h! Y' X
AFN表示的是file_id   
9 G$ L6 ]' ~% k, C  N% O9 k$ n  K8 TSelect file_name,tablespace_name,file_id “AFN”,relative_fno “RFN”  + Y- Y) Z- X7 f" j
From dba_data_files;   ) ^" C2 @: |  k/ L& x, n
Select file_name,tablespace_name,file_id, relative_fno“RFN”  
5 h- v; Y4 D( K5 j5 V4 I% e5 NFrom dba_temp_files;   ; y4 q5 I+ S* Y* V! ~( T& O
) v2 K8 _; R$ ?5 Q" S% n
  2. 确定存在坏块的对象是什么:   
( I. V3 q% b6 [- G& z3 L) a2 `4 p' i4 ~! E4 A
SELECT tablespace_name, segment_type, owner,   % ~/ O; e4 y0 `" g
segment_name, partition_name FROM   
0 ?9 @3 U/ K& z2 G5 B( \3 @2 `dba_extents WHERE file_id = and   
( p3 j6 d: I# U1 n8 _! U. A) z& Sbetween block_id AND block_id + blocks – 1;   
  T. [% U4 w' _& ?6 m( E$ `. [
. I6 |, V( Q" @$ x7 s3 l  通过上面这个查询语句就可以查出当前存在坏块的对象是什么,是什么类型的对象。需要注意的是如果是temp文件中出现坏块,是没有记录返回的。  
4 S6 v% T+ t2 \1 ^. c
3 b0 A7 c+ B' s  3. 根据2中查询出来的对象类型,确定相应的处理方法   3 z' ^, q: k1 ]% h1 q: N5 f
  出现坏块的常见对象有:   / V) h" I  C' J7 n
  Sys用户下的对象   
0 M* H0 [! ^# P/ `1 w4 d  回滚段   # Z; @3 r! `- `
  临时段   
5 u1 t& G' Z# d& C6 Z4 K  索引或者分区索引   
- C/ U6 k5 M, E. @  表   
4 A- _- M% \" t# G% [  常用的处理方法有:   
( b, K* m3 r' c8 H( m  恢复数据文件   : n9 p( J; w/ q" Y
  只恢复坏的block(9i以上版本可用)   
6 z: Y( g6 \2 W1 w8 z- b$ Y
9 t! Y, D3 ?1 l  F( s! O- D) O2 k  通过ROWID RANGE SCAN 保存数据   ; B: i7 L' `. }, K8 o  M' `& \
  使用DBMS_REPAIR   
" H% S- l: t0 N% Y5 P) ~  使用EVENT
回复

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:20 | 显示全部楼层

Oracle数据库中的坏块的技术

4. 具体处理方法的介绍   
/ [8 G  }8 D2 [1 T1 q
  C# J! o1 g" C5 O! Z  恢复数据文件方法:   0 E+ j, J6 {" L2 |
  如果数据库是归档方式下,并且有完整的物理备份,就可以使用此方法来恢复。  
  v5 b" r9 n' C- P. H- H  a1 j* b. l  步骤如下:   5 B2 d* X  r1 i$ Z" e! z" g
  (1) 先offline受影响的数据文件,执行以下的语句:   : U# v0 [! s* }& X  e

, \! S: R1 p$ J1 G5 {5 B1 m5 [' k; mALTER DATABASE DATAFILE ’name_file’ OFFLINE;  
0 p/ I( v* A9 l5 p4 `, W' o5 H% s$ B  (2) 保留有坏块的数据文件,然后拷贝备份的数据文件。如果恢复的数据文件要求路径不同,执行以下的语句:   
7 x7 `& `0 U' N" ^! Y# [! jALTER DATABASE RENAME FILE ’old_name’ TO ’new_name’;   / L1 b( E4 t' U6 M
2 O$ S9 z9 U: D* y% Q- C
  (3) 恢复数据文件,执行以下语句:   
9 @* t! y9 r2 K3 |- q: IRECOVER DATAFILE ’name_of_file’;   + t5 X. j8 Y, d3 r. b8 a
4 t/ P$ M* i' |
  (4) Online恢复后的数据文件,执行以下的语句:   8 L- C/ i$ u# ]; B

1 l& T7 f/ j8 a  o: b- AALTER DATABASE DATAFILE ’name_of_file’ ONLINE;   
& W  T. k: w; q9 ?) v. l, Y& b   只恢复坏的block(9i以上版本可用)   9 C3 `) ?, s5 v: f/ s

( X( M8 B+ w, x! L. z) n+ f  使用这种方法要求数据库版本是9.2.0以上,要求配置了Rman的catalog数据库,数据库为归档方式,并且有完整的物理备份。   
* q9 ~- V& ]; U# d' L% P  i步骤如下:   
) k- z5 m5 p7 Z# x" G3 r" v; n使用RMAN的BLOCKRECOVER命令 :   9 w$ ]" {+ q& Z  Y; }, h
4 o" J2 Y& |. P& J
Rman>run{blockrecover datafile 5 block 11,16; }   : j+ e8 A* D6 M% f' `0 V) G
) S. I# \- G* b: ?
  也可以强制使用某个SCN号之前的备份,恢复数据块。   
! U- h0 u2 @4 L" J! {Rman>run{blockrecover datafile 5 block 11,  
6 [" K. q2 i( c16 restore until sequence 8505; }   
" P9 _6 Z. ]8 g* v  ^' [  N/ P/ T8 U
4 h: |+ e4 J" ~1 |- H- p  y& I  V* n  通过ROWID RANGE SCAN 保存数据   : ?' m1 z9 |; r4 z  r% m. M
$ b1 x$ i# E! V0 e
  (1) 先取得坏块中ROW ID的最小值,执行以下的语句:   8 M$ @7 b' _& ~" ]
SELECT dbms_rowid.rowid_create(1,,  + Q0 {: h5 D2 ?* F
,,0) from DUAL;   4 l3 T, ~* z$ b! r" w8 I

" r  `& G; g5 ]! e% \7 R  g  (2)取得坏块中的ROW ID的最大值,执行以下的语句:   : {$ I/ l0 O# q! U0 \
SELECT dbms_rowid.rowid_create(1,,  4 @) O$ J2 b# X7 M# ~! a. i9 Q
,+1,0) from DUAL   / Z, a9 }9 J& b7 `

% \. J, |/ H* ]  (3)建议一个临时表存储那些没有坏块的数据,执行以下的语句:   " E# }4 \0 e' p! ^' {
  h! g" |6 U1 F$ t' G# j* `
CREATE TABLE salvage_table   & o: M  f$ l3 w" ^) O( P0 Y
AS SELECT * FROM corrupt_tab Where 1=2;   * v; s& b  e. t# z/ {* o, j

/ J) t+ s, s1 C5 l2 h4 }- B* C! Q' [6 v  (4) 保存那些不存在坏块的数据到临时表中,执行以下的语句:   
3 Q2 W! K. Z( A' |. a+ u0 A! ^9 k2 U
INSERT INTO salvage_table SELECT /*+ ROWID(A)   , ~, U0 T' ~  d" `6 n! g/ Q3 i- R# O
*/ * FROM A WHERE rowid < ’’;  2 u, l/ J) N: |; [
INSERT INTO salvage_table SELECT /*+ ROWID(A)   / b) ^6 q" f* x0 m1 z9 w
*/ * FROM A WHERE rowid >= ’‘;   
, \8 u- y; z3 u
) {3 o. K+ g+ d0 K$ n) k  (5) 根据临时表中的数据重建表,重建表上的索引,限制。   . w$ V. W4 i* Q2 a9 C7 E  g& {
  使用10231诊断事件,在做全表扫描的时候跳过坏块   
8 c( y/ v' t* r5 J# ~  可以在session级别设定:   - K& K* N2 ^5 U; Z7 |6 M# @
ALTER SESSION SET EVENTS ’10231   * H) H4 _9 h: |/ [0 q  {
TRACE NAME CONTEXT FOREVER, LEVEL 10’;   
, A: `' z; {3 B  Z  O; |4 ?. w+ y8 p/ g* c+ h( M' B; ?( e
  也可以在数据库级别上设定,在初始化参数中加入:event="10231 trace name context forever, level 10" ,然后重启数据库。   
0 ^9 s: ?' q& h: A, {' c
% b& W5 T3 b" ~  然后从存在坏块的表中取出不存在坏块的数据,执行以下的语句:   
' w* H& C9 e, h, R1 q( q8 a3 p( `( ECREATE TABLE salvage_emp AS SELECT * FROM corrupt_table;   1 G! t, ]9 k/ n& {1 e+ B
  最后rename生成的corrupt_table为原来表的名字,并重建表上的索引和限制。   
3 B' }9 i% M7 b  使用dbms_repair包进行恢复   6 p7 S0 [/ U- b( l
  使用dbms_repair标记有坏块的表,在做全表扫描的时候跳过坏块,执行以下的语句:   " o. |" `# K* |! E  O) {
Execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS  
: e- q9 @7 s8 B* {  s5 C* T(’’,’’);
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 14:06:21 | 显示全部楼层

Oracle数据库中的坏块的技术

然后使用exp工具或者createtable as select的方法取出没有坏块数据,然后重建表,表上的索引和限制。   
" Z" X/ _; c5 V  坏块的预先发现的方法   : H. Y( v+ i& U" Q

1 V: k1 W5 ^) |# V8 |( Y  1. 如果要检测数据库中所有的表,可以利用exp工具导出整个数据库可以检测坏块。不过这个工具有一些缺陷,对以下情况的坏块是检测不出来的:   
: ^( K1 \4 W7 I; r) e  HWM以上的坏块是不会发现的   
' K, U( s* l; A/ G  索引中存在的坏块是不会发现的   
$ Z4 P: D7 ~+ C
- d( Z+ i' C; h5 U( G* n+ [& M( s7 @  数据字典中的坏块是不会发现的   . D9 D# J! b- x" O, @5 n/ Z5 G# C2 i
  2. 如果只是对数据库中比较重要的表进行坏块检查,可以使用ANALYZE TABLE tablename VALIDATE STRUCTURE CASCADE 的方法来检测坏块,它执行坏块的检查,但是不会标记坏块为corrupt,检测的结果保存在USER_DUMP_DEST目录下的用户trace文件中。   ; }: t: P* F! o& m9 j3 t
5 f/ r- H6 |9 |+ @# q
  3. 使用Oracle的专门工具dbv来检查坏块,具体的语法如下:   5 k  ^0 j: q0 r8 |2 K6 H
  J6 e! f" J+ b2 m; e7 O
关键字 说明 (默认)  
3 @0 \1 _; i% B' }8 l8 }----------------------------------------------------  
0 U) Z) h+ K& {: g$ R' @& @/ X  [( dFILE 要验证的文件 (无)  + T. A2 e% I5 D% c
START 起始块 (文件的第一个块)  + t. V1 {( k/ Z* j% t
END 结束块 (文件的最后一个块)  7 \4 [, m9 [2 d* b; e5 N
BLOCKSIZE 逻辑块大小 (2048)    X7 {5 Q( j1 y2 U# U
LOGFILE 输出日志 (无)  : g- {% K% J; S4 i4 p4 i, G) a$ X
FEEDBACK 显示进度 (0)  ( E$ \% Z  p( |+ T
PARFILE 参数文件 (无)  4 A. f9 t1 ~: \# Z" d
USERID 用户名/口令 (无)  
9 M; ?# K2 a% u! cSEGMENT_ID 段ID (tsn.relfile.block) (无)   
( y8 ]5 d) n2 O9 k6 n- P, J: U- ]2 m/ ^9 T
例:   9 ~5 v* J4 j5 Q
2 l  M& H  K9 p4 @
Dbv file=system01.dbf blocksize=8192  : j! Z3 E! B) |: I
DBVERIFY: Release 9.2.0.5.0 - Production on 星期六 11月 27 15:29:13 2004  
% s! }# S6 B& Y+ Q9 pCopyright (c) 1982, 2002, Oracle Corporation. All rights reserved.  & C! b  z+ p  r9 Q; k
DBVERIFY - 验证正在开始 : FILE = system01.dbf  
& D' k) N/ ]! ^3 _DBVERIFY - 验证完成  2 l5 k" x, ]6 h# ?6 V
检查的页总数 :32000  5 A/ ~" i; g3 A' v1 J* X
处理的页总数(数据):13261  : k. k6 P/ K1 e  R; J7 }+ G
失败的页总数(数据):0  ; e5 P% _: m2 n  ^& O5 K. |& ?
处理的页总数(索引):2184  
1 h2 N  a3 p& v8 @9 M失败的页总数(索引):0  
! W, K5 ?: b7 O: R8 R$ ^处理的页总数(其它):1369  
7 x( @) r; U8 U+ R处理的总页数 (段) : 0  " H! {- }1 u  ^; u% f2 B1 D% J
失败的总页数 (段) : 0  
7 X9 V" p. O, t: A1 W. `5 q空的页总数 :15186  
/ G5 U( {; T1 `) U: P; a. Z. [1 @, a记为损坏的总页数:0  4 O# i9 t2 H, u& r) L$ A0 E9 x5 L
汇入的页总数 :0     Q, M# n% x: }  A5 u# x
: G, ~4 o/ u3 c! s3 W
  注释:由于dbv要求file后面跟的必须是一个文件扩展名,所以如果用裸设备存储的,就必须使用ln链接裸设备到一个文件,然后再用dbv对这个链接文件进行检查。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-9-28 06:32 , Processed in 0.235499 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表