第一部分 . 概述
一、 实验环境
运行环境:
[root@localhost ~]# lsb_release -a
LSB Version: :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch
Distributor ID: RedHatEnterpriseServer
Description: Red Hat Enterprise Linux Server release 5.4 (Tikanga)
Release: 5.4
Codename: Tikanga
数据库版本:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
二、 实验目标
使用bbed工具对hr用户下的departments表所在的一个块进行破坏,然后使用RMAN block recover进行块恢复。
第二部分 . 技术概述
一、 实验步骤
1. Linking bbed
在使用bbed工具前必须先link,bbed的代码会和oracle的数据库一起装载在unix或者linux上,但是并没有被linked。
a) 编译bbed
[oracle@lzc lib]$ make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed
Linking BBED utility (bbed)
rm -f /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/bbed
gcc -o /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/bbed -L/u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/ -L/u01/app/oracle/product/10.2.0.1/db_1/lib/ -L/u01/app/oracle/product/10.2.0.1/db_1/lib/stubs/ -L/usr/lib -lirc /u01/app/oracle/product/10.2.0.1/db_1/lib/s0main.o /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/ssbbded.o /u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib/sbbdpt.o `cat /u-ldl
。。。(省略部分)
-lm -L/u01/app/oracle/product/10.2.0.1/db_1/lib
查看一下是否成功编译
[oracle@lzc lib]$ ll bbed
-rwxr-xr-x 1 oracle oinstall 536161 Aug 31 09:50 bbed
可以看到成功编译!
b) 设置环境变量
为了使用方便,在任何目录下都能够随意调用bbed的命令,我们可以把bbed所在的目录/u01/app/oracle/product/10.2.0.1/db_1/rdbms/lib添加到path环境变量下,或者做一个软连接。
这里我选择第一种。
至于如何添加修改PATH环境变量,就不用多说了。在/home/oracle目录下修改.bash_profile文件即可。
2. Starting bbed
a) 创建listfile文件filelinux.log
SQL> select file#||' '||name||' '||bytes from v$datafile;
FILE#||''||NAME||''||BYTES
--------------------------------------------------------------------------------
1 /u01/app/oracle/oradata/dblzc/system01.dbf 513802240
2 /u01/app/oracle/oradata/dblzc/undotbs01.dbf 83886080
3 /u01/app/oracle/oradata/dblzc/sysaux01.dbf 293601280
4 /u01/app/oracle/oradata/dblzc/users01.dbf 15728640
5 /u01/app/oracle/oradata/dblzc/soe.dbf 3436183552
b) 创建parfile文件bbed.par
blocksize=8192 //该参数为数据库的default block size
listfile=/home/oracle/bbed_test/filelinux.log //上面创建的listfile文件
mode=edit //进入bbed的模式,有browse和edit两个参数。在browse模式下只能浏览,不能进行修改。
c) 查看要修改的数据库块的信息
1* select file_id,owner,segment_name,block_id from dba_extents where segment_name='DEPARTMENTS' and WNER='HR'
FILE_ID OWNER SEGMENT_NAME BLOCK_ID
---------- ----- -------------------- ----------
4 HR DEPARTMENTS 121
这里的的block_id指的是这个块所在区的第一个块的block_id
d) 查看表中记录的信息
SQL> select * from departments;
DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID
------------- ------------------------------ ---------- -----------
10 Administration 200 1700
20 Marketing 201 1800
50 Shipping 124 1500
60 IT 103 1400
80 Sales 149 2500
90 Executive 100 1700
110 Accounting 205 1700
190 contracting 1700
8 rows selected.
e) 查看每行记录对应存储的块号
SQL> select dbms_rowid.rowid_block_number(rowid) from departments;
DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
127
127
127
127
127
127
127
127
8 rows selected.
这里可以看到表中每行数据所在的block_id。由于测试数据比较少,所以departments这个表中的所有数据都在127这个数据块中。
从以上的查询我们可以获得我们所要操作的块的相关信息。假设我们现在修改department表所在的块的信息。File_id=4 block_id=127
3. 进入bbed
[oracle@lzc bbed_test]$ bbed parfile=bbed.par
Password:
BBED: Release 2.0.0.0.0 - Limited Production on Fri Aug 31 11:42:16 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
************* !!! For Oracle Internal Use only !!! ***************
BBED>
BBED的密码是blockedit,这个密码在任何客户端上都是一样的。如果你对这个工具的oracle内部安全代码足够了解,也可以使用standard reverse-engineering技术进行修改。
可以通过下面两个命令来查看,刚在在参数文件中设置的参数
BBED> show
FILE# 4
BLOCK# 127
OFFSET 7554
DBA 0x0100007f (16777343 4,127)
FILENAME /u01/app/oracle/oradata/dblzc/users01.dbf
BIFILE bifile.bbd
LISTFILE /home/oracle/bbed_test/filelinux.log
BLOCKSIZE 8192
MODE Edit
EDIT Unrecoverable
IBASE Dec
OBASE Dec
WIDTH 80
COUNT 512
LOGFILE log.bbd
SPOOL No
BBED> info
File# Name Size(blks)
----- ---- ----------
1 /u01/app/oracle/oradata/dblzc/system01.dbf 62720
2 /u01/app/oracle/oradata/dblzc/undotbs01.dbf 10240
3 /u01/app/oracle/oradata/dblzc/sysaux01.dbf 35840
4 /u01/app/oracle/oradata/dblzc/users01.dbf 1920
5 /u01/app/oracle/oradata/dblzc/soe.dbf 419456
4. 修改块中的数据
a) 设置当前数据块
BBED> set dba 4,127
DBA 0x0100007f (16777343 4,127)
参数dba为数据块的地址data block address
假设现在我要修改departments表中包含’Sale’字符的那一行
BBED> find /c Sale
File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 127 Offsets: 7554 to 8065 Dba:0x0100007f
<32 bytes per line>
通过find命令我们可以找到改行在127块中的offsets
b) 查看块中的内容
然后我们可以通过改行所在的offset查看对应存储在块中的数据
BBED> dump /v dba 4,127 offset 7554 count 5
File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 127 Offsets: 7554 to 8065 Dba:0x0100007f
-------------------------------------------------------
53616c65 7303c202 3202c21a 2c020402 l Sales.�.2.�.,...
Dump命令使用来显示指定的块的内容,通过offset可以更进一步查看到每一行中的内容。
通过count参数控制向屏幕输出的字节数。要根据你所要查找的字符的长度来设置。
c) 修改块中的内容
BBED> modify /c lanzaichen dba 4,127 offset 7554
File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 127 Offsets: 7554 to 8065 Dba:0x0100007f
------------------------------------------------------------------------
6c616e7a 61696368 656ec21a 2c020402 c13d0249 5403c202 0402c20f 2c020402
c1330853 68697070 696e6703 c2021902 c2102c02 0402c115 094d6172 6b657469
6e6703c2 030202c2 132c0204 02c10b0e 41646d69 6e697374 72617469 6f6e02c2
0302c212 3c020403 c2025b0c 20636f6e 74726163 74696e67 ff02c212 3c020403
c2020b0a 4163636f 756e7469 6e6703c2 030602c2 123c0204 02c15b09 45786563
部分省略。。。
再次重新查看一下块中的内容
BBED> dump /v dba 4,127 offset 7554 count 10 File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 127 Offsets: 7554 to 8065 Dba:0x0100007f
-------------------------------------------------------
6c616e7a 61696368 656ec21a 2c020402 l lanzaichen
可以看到第一行中的数据已经被修改掉,如果此时我们不对刚才的操作执行sum命令apply修改的话。由于校验值发生了变化,在数据库中这个数据块就会报错。
然后回到数据库中重新查看表中的数据,看是否能够正常检索。
5. 诊断坏块
前面我们已经成功的修改了departments表所在的块的内容,由于没有使用sum命令apply设置。所以,被修改的块不能被正常检索。那我们如何找到这个坏块呢?
a) 通过检索数据
在检索数据时会对数据所在的数据文件进行扫描(被检索的数据不在内存中),可以检测到数据文件中的坏块。
SQL> conn / as sysdba
Connected.
SQL> alter system flush buffer_cache;
System altered.
从表中检索内容之前要先把数据库高速缓冲区(data buffer cache)中的数据清除。
SQL> conn hr/oracle
Connected.
SQL> select * from departments;
select * from departments
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 127)
ORA-01110: data file 4: '/u01/app/oracle/oradata/dblzc/users01.dbf'
可以看到,我们刚才修改的数据被报错。
b) Dbverify工具
SQL> select block_size from v$datafile where file#=4;
BLOCK_SIZE
----------
8192
SQL> host
[oracle@lzc ~]$ dbv file=/u01/app/oracle/oradata/dblzc/users01.dbf blocksize=8192
DBVERIFY: Release 10.2.0.1.0 - Production on Fri Aug 31 15:29:13 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
DBVERIFY - Verification starting : FILE = /u01/app/oracle/oradata/dblzc/users01.dbf
Page 121 is marked corrupt
Corrupt block relative dba: 0x01000079 (file 4, block 121)
Bad header found during dbv:
Data in bad block:
type: 67 format: 7 rdba: 0x0a545055
last change scn: 0x0000.00149f2b seq: 0x2 flg: 0x04
spare1: 0x52 spare2: 0x52 spare3: 0x0
consistency value in tail: 0x9f2b2002
check value in block header: 0xd12
computed block checksum: 0xe449
Page 122 is marked corrupt
Corrupt block relative dba: 0x0100007a (file 4, block 122)
Bad header found during dbv:
Data in bad block:
type: 67 format: 7 rdba: 0x0a545055
last change scn: 0x0000.00149e97 seq: 0x2 flg: 0x04
spare1: 0x52 spare2: 0x52 spare3: 0x0
consistency value in tail: 0x9e972102
check value in block header: 0x4dd4
computed block checksum: 0xe44b
Page 127 is marked corrupt
Corrupt block relative dba: 0x0100007f (file 4, block 127)
Bad check value found during dbv:
Data in bad block:
type: 6 format: 2 rdba: 0x0100007f
last change scn: 0x0000.00149fa2 seq: 0x1 flg: 0x06
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0x9fa20601
check value in block header: 0xae4a
computed block checksum: 0x73d9
DBVERIFY - Verification complete
Total Pages Examined : 1920
Total Pages Processed (Data) : 347
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 134
Total Pages Failing (Index): 0
Total Pages Processed (Other): 1130
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 306
Total Pages Marked Corrupt : 3
Total Pages Influx : 0
Highest block SCN : 1559918 (0.1559918)
可以看到有两个坏块被检测数122和127。不过121,122可能是实验前就存在的坏块。详细信息看后面的实验分析,会有具体介绍。
c) 使用analyze命令
SQL> analyze table departments validate structure cascade;
analyze table departments validate structure cascade
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 121)
ORA-01110: data file 4: '/u01/app/oracle/oradata/dblzc/users01.dbf'
更多的检查工具就不一一介绍了。下面使用rman blockrecover命令进行恢复。
6. 执行恢复
执行恢复命令
RMAN> blockrecover datafile 4 block 121;
RMAN> blockrecover datafile 4 block 122;
RMAN> blockrecover datafile 4 block 127;
再次查看一下departments表看看数据是否成功恢复
SQL> select * from departments;
DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID
------------- ------------------------------ ---------- -----------
10 Administration 200 1700
20 Marketing 201 1800
50 Shipping 124 1500
60 IT 103 1400
80 Sales 149 2500
90 Executive 100 1700
110 Accounting 205 1700
190 contracting 1700
8 rows selected.
可以看到数据被成功恢复!
二、 实验分析
1. 问题一如何判断坏块的位置
在文档中诊断坏块部分我们说道,我破坏了一个快127,在检索的时候遇到了122,和121
这两个坏块。现在我们来看看这两个坏块分别位于哪个表所在的段中
SQL> select owner,block_id,segment_name from dba_extents where tablespace_name='USERS' AND block_id=121;
OWNER BLOCK_ID SEGMENT_NAME
----- ---------- --------------------
HR 121 DEPARTMENTS
SQL> select owner,block_id,segment_name from dba_extents where tablespace_name='USERS' AND block_id=122;
no rows selected
可看到121这个坏块也属于departments这个段中。至于122为啥没找到这个,我分析了一下结果是。。。。。。嘿嘿,不知道。
你可能会问我,为什么刚才在使用select * from departments; 命令时就看到一个坏块呢,这是因为departments这个表当前的数据只占用了127 一个块,在检索数据时也就只检索了这一个块。所以没有报错。
2. 问题二在bbed工具中使用find查找命令时找不到目标字符串
a)可能是因为数据在修改提交后的数据被保存在数据库高速缓存中没有写入数据文件
这时候可以执行一次检查点事件Alter system checkpoint;
这种情况就不演示了
b) offset的值低于当前current offset的值。
这种情况在这里给大家模拟一下
1) 在scott用户下新建一个test测试表SQL> desc test;
Name Null? Type
----------------------------------------- -------- ----------------------------
TSCN CHAR(10)
SQL> show user;
USER is "SCOTT"
2) 向其中插入两条数据SQL> insert into test values('&var');
Enter value for var: ab
old 1: insert into test values('&var')
new 1: insert into test values('ab')
1 row created.
SQL> r
1* insert into test values('&var')
Enter value for var: cd
old 1: insert into test values('&var')
new 1: insert into test values('cd')
1 row created.
查看插入的数据
SQL> select * from test;
TSCN
----------
ab
cd
3) 查看创建的测试表的file_id,以及block_idSQL> select file_id,block_id,bytes from dba_extents where segment_name='TEST' AND wner='HR';
FILE_ID BLOCK_ID BYTES
---------- ---------- ----------
4 65 65536
SQL> select dbms_rowid.rowid_block_number(rowid) from test;
DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
68
68
4) 使用bbed工具查看块信息在获得我们想要的信息之后现在我们可以进入bbed查看对应块中的数据了
BBED> set dba 4,68
DBA 0x01000044 (16777284 4,68)
设置当前操作块为68,使show命令看一下当前的参数设置是否正确
BBED> show all
FILE# 4
BLOCK# 68
OFFSET 0
DBA 0x01000044 (16777284 4,68)
FILENAME /u01/app/oracle/oradata/dblzc/users01.dbf
BIFILE bifile.bbd
LISTFILE /home/oracle/bbed_test/filelinux.log
BLOCKSIZE 8192
MODE Edit
EDIT Unrecoverable
IBASE Dec
OBASE Dec
WIDTH 80
COUNT 512
LOGFILE log.bbd
SPOOL No
5) 查找一行数据的offsetBBED> find /c ab
File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 68 Offsets: 8178 to 8191 Dba:0x01000044
------------------------------------------------------------------------
61622020 20202020 20200406 a91b
<32 bytes per line>
BBED> dump /v offset 8178
File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 68 Offsets: 8178 to 8191 Dba:0x01000044
-------------------------------------------------------
61622020 20202020 20200406 a91b l ab ..�.
<16 bytes per line>
可以看到test表中第一行的值正常显示。
6) 查找第二行记录的offset现在,我们查看第二行记录的值。
BBED> find /c cd
BBED-00212: search string not found
没有找到,怎么会没有找到呢?难道是dba地址设错了?现在我们show 命令看一下详细信息
BBED> show all
FILE# 4
BLOCK# 68
OFFSET 8178
DBA 0x01000044 (16777284 4,68)
FILENAME /u01/app/oracle/oradata/dblzc/users01.dbf
BIFILE bifile.bbd
LISTFILE /home/oracle/bbed_test/filelinux.log
BLOCKSIZE 8192
MODE Edit
EDIT Unrecoverable
IBASE Dec
OBASE Dec
WIDTH 80
COUNT 512
LOGFILE log.bbd
SPOOL No
从上面我们可以看到dba的设置没有错误啊,再细看,看到没用红色标出的部分。没错,offsets的值发生了变化,第一次我们show 命令的时候是0而我们第二次show的时候是8178。
你或许会问,既然都是在一个块上,find的查找和offset查找又有什么关系呢?
这就要关联到block的结构了。向块中存储数据时,是从下往上写入,先写入的数据在下面,后写入的值在上面。而且后写入的数据也就是在上面的数据的offset值要小于先写入的。
而find命令查找数据的方式是从current offset开始向下查找。由于在我find一条记录是offset的值已经变为8178,大于第二条记录的offset。所以当我查找第二条记录时find会从offset=8178 开始先下搜索。这样自然就无法找到后加入的记录的值了。
既然了解了,就不用我多说了,只需要把offset的值设为0,就不怕找不到了。
7) 重设offset的值BBED> set offset 0
OFFSET 0
BBED> find /c cd
File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 68 Offsets: 8164 to 8191 Dba:0x01000044
------------------------------------------------------------------------
63642020 20202020 20202c01 010a6162 20202020 20202020 0406a91b
<32 bytes per line>
可以看到第二条记录的offset值小于第一条记录。
再看一下从 offset8164到8191之间的数据
BBED> dump/v offset 8164 count 27
File: /u01/app/oracle/oradata/dblzc/users01.dbf (4)
Block: 68 Offsets: 8164 to 8190 Dba:0x01000044
-------------------------------------------------------
63642020 20202020 20202c01 010a6162 l cd ,...ab
20202020 20202020 0406a9 l ..�
<16 bytes per line>
可以看到第一天插入的记录的值位于第二条插入记录的值得后面。
最终成功找到了数据!
三、 实验小结
总结一点,使用rman 的blockrecover 恢复块是一定要有备份的,要有归档日志。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26723566/viewspace-742657/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/26723566/viewspace-742657/