a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 114|回复: 2

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

[复制链接]
发表于 2012-8-4 14:06:19 | 显示全部楼层 |阅读模式
数据库的数据块有固定的格式和结构,分三层:cache layer,transaction layer,data layer。在我们对数据块进行读取写入操作的时候,数据库会对要读写的数据块做一致性的检查,其中包括:数据块的类型、数据块的地址信息、数据块的SCN号以及数据块的头部和尾部。如果发现其中有不一致的信息,那数据库就会标记这个数据块为坏块了。数据库的坏块分为两种,逻辑坏块和物理坏块。   9 F, V* @. K! ?6 F# r

3 p' r3 X' @2 i$ g/ T  坏块对数据库产生的影响:   + `! S# p4 z& i3 a
# f! C1 C: u4 |; [: `9 q* ]
  如果数据库出现坏块,数据库的告警日志文件里面会存在有如下的一些报错信息:Ora-1578以及Ora-600 and trace file in bdump directory,其中Ora-600错误的第一个参数值的范围是[2000]-[8000],不同的值代表着数据块的不同的层出现问题,参照下表:   
5 h. _9 Q, W7 W* B. }% M9 t/ R" O  D7 q3 s
Range block layer  * `2 I  K7 K+ V6 p# O# r6 f
Cache layer 2000 – 4000  
" P! K+ g0 G+ W4 ^+ TTransaction layer 4000 – 6000  ' V6 t* v; Z6 C
Data layer 6000 - 8000  7 t! g4 K4 `9 Z7 f4 B

( R* N& z- J+ _; `8 Q  坏块产生影响的对象可能是数据字典表、回滚段表、临时段、用户数据表和索引等。不同的对象产生坏块后的处理方法不尽相同。   
5 A( W4 T% Q, ?( v) p9 U
+ P$ Y  V4 o$ M; Z6 @9 h/ t8 w, ?9 j  三:坏块产生的原因   
) o. d5 a* y1 D) j6 ]# D0 h2 U5 J
) t: C) B8 K9 ~5 D7 x1 e  Oracle调用标准C的系统函数,对数据块进行读写操作,因此,坏块是有可能由以下几种原因产生:   0 |% h3 v# f( o: `' R9 A

9 x) i2 q/ T6 g/ m' K  硬件的I/O错误   
' e7 H  E! M7 n. z& r6 A. [  操作系统的I/O错误或缓冲问题   
4 Y4 ^; a% @! d+ `  T  内存或paging问题   
! R& ]& c( |1 e% m& G% [. g  磁盘修复工具   & [' P0 U; q0 b1 U. |' E$ v1 z9 i
  一个数据文件的一部分正在被覆盖   3 T4 f, C% t5 @/ k  w
  Oracle试图访问一个未被格式化的系统块失败   
- P* w9 g$ u' H* T; d8 X+ D  数据文件部分溢出   2 @2 b* Z8 L* a9 G  K* k2 B3 a) G( d
  Oracle或者操作系统的bug   
& g- d& F. o+ }! v; E# E
3 y) L; j5 Y1 |# J! e" O: u: e  o  坏块的处理方法   2 C% g/ @* d9 F6 y* l
  1. 先收集相应的关于坏快的信息,从AlertSID.log文件或者从trace文件中查找,找到例如以下的一些信息:   * O8 k; L9 r- Y+ t( e% O' M9 H

7 k- \  D  d7 I0 w+ g# X& Q9 ]Ora-1578 file# (RFN) block#  ! W, p6 `4 P1 H/ H
Ora-1110 file# (AFN) block#  - w# z" N$ t  |
Ora-600 file# (AFN) block#   / Z; ^; S( d2 a1 f
其中RFN表示的是relative_fno   , \8 T7 j6 }# \, N
AFN表示的是file_id   & w' {+ h2 B  a1 d
Select file_name,tablespace_name,file_id “AFN”,relative_fno “RFN”  $ C) h, s: |' F
From dba_data_files;   
8 d# J: L) {# [/ L, y# cSelect file_name,tablespace_name,file_id, relative_fno“RFN”  9 u5 d, v4 ^3 h7 |6 ^) f  ^1 R
From dba_temp_files;   
8 P5 Z8 O0 P) h( L: F# H" K$ l9 m, o4 V1 P! p5 A
  2. 确定存在坏块的对象是什么:   
4 H! Y4 [1 i3 [, d' N" l- Z: H3 I
SELECT tablespace_name, segment_type, owner,   ( f$ m* y5 B, A0 U/ G1 \- o- ]
segment_name, partition_name FROM   $ s: K$ ~: f$ L% D9 f
dba_extents WHERE file_id = and   
$ v2 H. ^% k% e" L1 }8 vbetween block_id AND block_id + blocks – 1;   ' n0 a; N' f) l8 c% x& ~- N& Z
3 ^. Y7 l7 y8 c1 D
  通过上面这个查询语句就可以查出当前存在坏块的对象是什么,是什么类型的对象。需要注意的是如果是temp文件中出现坏块,是没有记录返回的。  6 F4 Y% t+ r7 L

) z1 W5 N( ?3 X/ M& M  3. 根据2中查询出来的对象类型,确定相应的处理方法   / [" A! \4 Y& X' D
  出现坏块的常见对象有:   
8 ?& X" v* n' U( }& U  Sys用户下的对象   
: a! D9 v1 _( A1 w% b0 z3 o  回滚段   
9 @, a. B; g9 r0 U7 K+ M  临时段   
% b- o: G% s4 V. K! v  索引或者分区索引   ! Q2 p3 [% p% }$ j7 S6 S: X0 _
  表   1 S+ K  G2 J' t  f7 l
  常用的处理方法有:   
- M, {0 [+ k) u2 g" q2 E) p. @  恢复数据文件   
: X% Y3 m9 {. N8 a$ y9 c+ K4 q  只恢复坏的block(9i以上版本可用)   ) u( Y* p- P+ G% x- V& q
* [. n& s3 o1 a+ a+ z( O5 i
  通过ROWID RANGE SCAN 保存数据   ) T. i: c" l6 @4 h! Z4 Q& s. L
  使用DBMS_REPAIR   + @* t4 e% d3 H
  使用EVENT
回复

使用道具 举报

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

Oracle数据库中的坏块的技术

4. 具体处理方法的介绍   
* h' V- o# O, ?* L  Q
$ G2 }! L2 R8 x7 O. {  恢复数据文件方法:   5 C3 I0 e; v: U, r0 }+ J
  如果数据库是归档方式下,并且有完整的物理备份,就可以使用此方法来恢复。  $ L; O/ Z2 g# t/ g
  步骤如下:   
- x* B5 ^% s8 V& p' X1 W. |' ^, q  (1) 先offline受影响的数据文件,执行以下的语句:   
% A* |4 H5 S1 O8 h; o; k7 t; p0 n  {9 o7 Z. }
ALTER DATABASE DATAFILE ’name_file’ OFFLINE;  
4 h. |  [  k& L2 m# y, d6 }  (2) 保留有坏块的数据文件,然后拷贝备份的数据文件。如果恢复的数据文件要求路径不同,执行以下的语句:   
4 [& m/ {. x) G$ nALTER DATABASE RENAME FILE ’old_name’ TO ’new_name’;   / j7 v2 A' N% a7 T7 S
" K( t6 l. f3 v" a! C' c% [+ [
  (3) 恢复数据文件,执行以下语句:   
9 [3 u3 [, v6 f  {0 s/ v; Y0 XRECOVER DATAFILE ’name_of_file’;   
# s" n" {0 D7 Y: A0 w4 k+ h. h% f( w
  (4) Online恢复后的数据文件,执行以下的语句:   
6 ]0 X6 B  \7 X  @' a; X0 k. ^! ~  c, m8 I) N% N
ALTER DATABASE DATAFILE ’name_of_file’ ONLINE;   
# `% X, }9 I7 _- A3 J! m% u   只恢复坏的block(9i以上版本可用)   & ^# Z6 [+ D' d9 i
, S1 a3 f% a1 I- i+ ^: z1 p
  使用这种方法要求数据库版本是9.2.0以上,要求配置了Rman的catalog数据库,数据库为归档方式,并且有完整的物理备份。   $ Q+ d& }0 X. w8 K6 m0 v
步骤如下:   
) G8 Q7 L2 x4 `0 o5 _. p% l使用RMAN的BLOCKRECOVER命令 :   . f$ ~) k: W" w' T$ ]+ c" h/ D  T
; C+ _9 ~9 W% o  Q) j7 t
Rman>run{blockrecover datafile 5 block 11,16; }   : }- ?. C/ I  C. g" D4 C1 r( d/ \) W4 L8 T

) Y2 ]. w( I- T! q2 `  也可以强制使用某个SCN号之前的备份,恢复数据块。   
* m) ?. s  q( w; l$ {  Y! Z+ ?Rman>run{blockrecover datafile 5 block 11,  
/ g+ l6 j7 |* v1 I  b16 restore until sequence 8505; }   * D$ r& N& ^& p: C' ^6 |

. p( e. e& v7 l$ @( D( p8 y4 E  通过ROWID RANGE SCAN 保存数据   ! S- C9 w& x  G6 V# e
3 ?! ]8 G$ ]! L3 N
  (1) 先取得坏块中ROW ID的最小值,执行以下的语句:   ! e5 j1 ~) x+ ^) m; B$ ^" Q" K
SELECT dbms_rowid.rowid_create(1,,  % ]* Y" y$ V. b" q
,,0) from DUAL;   9 |! S: b3 M6 X5 f

, j# t$ V$ B4 s  d7 y4 K0 k" [  (2)取得坏块中的ROW ID的最大值,执行以下的语句:   1 u2 M$ r7 O& |* d; X# V% e: y
SELECT dbms_rowid.rowid_create(1,,  
, Q& H6 l/ h' E9 H,+1,0) from DUAL   . k# |- t, v* j& Z7 ?0 m) o

0 _7 A" l' A/ c/ Z* ^! ^2 a  (3)建议一个临时表存储那些没有坏块的数据,执行以下的语句:   
/ h/ v& u6 {) T/ k/ |/ k. t2 L. _& M2 ^) J7 ~# T9 h7 z
CREATE TABLE salvage_table   
( ^0 x% z& Z* a' E3 o; F! \; U- r' Y* |AS SELECT * FROM corrupt_tab Where 1=2;   0 }0 t% m) k, L/ d, [+ r
7 \" p# @" P. K0 ~* p
  (4) 保存那些不存在坏块的数据到临时表中,执行以下的语句:   : x, ~" A, e- ]  `$ d; A
) t- u8 |6 l4 U3 G; D
INSERT INTO salvage_table SELECT /*+ ROWID(A)   
! y. y! Q5 U! m*/ * FROM A WHERE rowid < ’’;  
0 b- N  l4 R4 T  C8 e3 V# JINSERT INTO salvage_table SELECT /*+ ROWID(A)   
# F0 [5 {( K3 l' {% |3 z*/ * FROM A WHERE rowid >= ’‘;     f1 G# V  R- y! w' K/ S: u. H' A
6 O( F" _6 o0 m; l: r
  (5) 根据临时表中的数据重建表,重建表上的索引,限制。   ; D; F9 {' X# v! G# b) Y
  使用10231诊断事件,在做全表扫描的时候跳过坏块   : Q  m5 l( U* v7 e
  可以在session级别设定:   
  K0 [; C. g+ C' A7 F0 yALTER SESSION SET EVENTS ’10231   & }7 f0 j9 R' H9 u* `% u
TRACE NAME CONTEXT FOREVER, LEVEL 10’;   
# U. S- O6 \6 l3 d
7 O) [+ v( \/ L. F. t1 f  也可以在数据库级别上设定,在初始化参数中加入:event="10231 trace name context forever, level 10" ,然后重启数据库。   
5 _$ m" |4 Z8 W7 ^$ X
' z# ^6 h( e2 e0 g$ D9 F9 t6 X  然后从存在坏块的表中取出不存在坏块的数据,执行以下的语句:   " s; U& z9 [  a  n" e7 S
CREATE TABLE salvage_emp AS SELECT * FROM corrupt_table;   # a4 ^; c/ L) @# c- Z# X
  最后rename生成的corrupt_table为原来表的名字,并重建表上的索引和限制。   
( K+ e1 `3 o) b  使用dbms_repair包进行恢复   , w+ R) z* |# W, g; ?- d/ V
  使用dbms_repair标记有坏块的表,在做全表扫描的时候跳过坏块,执行以下的语句:   $ F, F( I' g. h! |
Execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS  . ~, V5 N7 K1 e/ d
(’’,’’);
回复 支持 反对

使用道具 举报

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

Oracle数据库中的坏块的技术

然后使用exp工具或者createtable as select的方法取出没有坏块数据,然后重建表,表上的索引和限制。   
% E1 f0 U+ I+ w3 d  坏块的预先发现的方法   
% w( Q2 q# @  c% Z
) r5 |/ Z- e7 r; \' R/ g9 G  1. 如果要检测数据库中所有的表,可以利用exp工具导出整个数据库可以检测坏块。不过这个工具有一些缺陷,对以下情况的坏块是检测不出来的:   
" Y& G6 ?- F) f' _/ T; \: K* }  HWM以上的坏块是不会发现的   
9 n" `) z1 b5 T: g  n  索引中存在的坏块是不会发现的   0 y$ n$ s9 K) }$ b  Q9 W  ~9 ~
" E. ]  L( `; q$ l
  数据字典中的坏块是不会发现的   
0 I- D$ _' p  E! Y  2. 如果只是对数据库中比较重要的表进行坏块检查,可以使用ANALYZE TABLE tablename VALIDATE STRUCTURE CASCADE 的方法来检测坏块,它执行坏块的检查,但是不会标记坏块为corrupt,检测的结果保存在USER_DUMP_DEST目录下的用户trace文件中。   
  ?( ^, k4 J1 a  Y& Q' @. _/ E1 H; F- E9 l) j+ y
  3. 使用Oracle的专门工具dbv来检查坏块,具体的语法如下:   . |) e% ~( Y5 Q* U$ ^6 K
! M7 o% t$ {& J# C& l
关键字 说明 (默认)  
; q. O1 N6 c! c" F4 d4 C! Y; B----------------------------------------------------  / {  g$ Y' v; q9 r+ @* v5 W
FILE 要验证的文件 (无)  
2 g& Q% q8 M4 |* B( u+ Z$ k& L# J+ x' kSTART 起始块 (文件的第一个块)  # E, u; D2 M$ y2 j% y) K& e" ?
END 结束块 (文件的最后一个块)  : R/ t$ X# n5 }, _5 m- W/ s
BLOCKSIZE 逻辑块大小 (2048)  / B0 G3 d2 m) \$ G& S7 k& r
LOGFILE 输出日志 (无)  " x  w; N9 O/ G- H
FEEDBACK 显示进度 (0)  7 ?& E# b4 @2 M7 I! a6 P
PARFILE 参数文件 (无)  
5 ]) ~1 ?- d& P- {' \3 a: @" fUSERID 用户名/口令 (无)  3 }1 c* k6 ^+ A# O( I' k4 L
SEGMENT_ID 段ID (tsn.relfile.block) (无)   
7 e* }& U, D3 ]/ c. A1 S3 e+ T  W0 @6 D# Y/ N  Y; F) `/ `8 F
例:   
; k( \9 p/ k! i% H* `4 E3 Z5 Q5 g7 f% i
Dbv file=system01.dbf blocksize=8192    i( x1 n/ ], |9 J! _+ ~0 R, A$ P
DBVERIFY: Release 9.2.0.5.0 - Production on 星期六 11月 27 15:29:13 2004  4 F& \# z0 B* W: ~7 U. j* Q' ?0 v7 Q6 U
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.  
: ^4 B: a7 o2 ]9 EDBVERIFY - 验证正在开始 : FILE = system01.dbf  $ y, u* v9 _5 c- O& _) f" {$ Q/ h% A! N
DBVERIFY - 验证完成  
  _$ e) U1 t6 L# F检查的页总数 :32000  
& F% K, @, r. k3 X; q% H处理的页总数(数据):13261  
  g. V0 i/ d3 |4 x' x2 U( \0 O失败的页总数(数据):0  
9 g5 B% `- ^  |# _处理的页总数(索引):2184  2 W" Y/ Y  ]% A7 f
失败的页总数(索引):0  ( F9 K6 D7 t& @9 k: f) ^
处理的页总数(其它):1369  
* d: h7 q' |( v处理的总页数 (段) : 0  ) E7 w% @/ O  G' Q! O0 k1 r$ o
失败的总页数 (段) : 0  
2 R  z6 h; P8 I' k/ _+ e$ y空的页总数 :15186  & H* H1 \; L' x/ x" A& [  r6 M
记为损坏的总页数:0  4 h3 b. a3 p) q2 j
汇入的页总数 :0   ( A8 U2 p0 O: |/ t
! C1 F/ p* i8 `
  注释:由于dbv要求file后面跟的必须是一个文件扩展名,所以如果用裸设备存储的,就必须使用ln链接裸设备到一个文件,然后再用dbv对这个链接文件进行检查。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-7 15:04 , Processed in 0.285860 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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