上周三中午CQ数据库数据文件损坏,导致登录时一张关键的表无法查询报错从而cq无法登录,此次故障和上次的一样,不过恢复的非常曲折,导致停机两天,现简单的通报下恢复过程:
oracle-902版本的一个BUG,数据文件大小逼近4G、8G临界点时无法自动扩展,该bug在903版本后得到修复,但是公司cq库迟迟未升级,14号数据文件上保存了大量的大对象数据以及大部分cq系统表,在执行修改操作段扩张时逼近4G大小临界点从而报错,导致数据文件头不一致,数据文件被offline。。。上次故障也是同样的问题。
最终的解决方案为重建14号数据文件所在的表空间,全部使用小数据文件(1.9G+10M增长)避免bug的触发。(当然中间经历千辛万苦,不得已才这么办)。
l 28号下午3点20时就恢复了,对全库做备份时发现磁盘空间不足,考虑到库已恢复成功,因此将历史备份全部删除释放磁盘空间,4:30左右备份完成。
l 再次登录cq,发现又报错,14号文件又坏了,其实在15:20时库已经恢复成功,由于印象中第一次故障时库只要重启后即无法再使用cq连接,基于这样一种经验,我将库打开后直接开始备份,我认为此时就我一个用户连在库上,但是其实已经很多同事悄悄连到该库开始使用,大约在4:10分左右14号文件就悄悄的坏了。。。
l 使用刚完成的rman恢复,发现14号文件已然损坏,原来在备份中间就损坏了。(28号下午5点半)
l 此时的状况是除了一个坏的备份没有其他备份,无法通过rman进行恢复。尝试隐含参数用尽各种常规办法均告失败,14号文件仍然无法open(28号晚9点)。
l 进行数据文件头伪造,手动修改header的scn等信息、重建控制文件等,骗过smon成功将库打开(29号晚11点)。
l 历尽千辛万苦,30号升级至11gR2,连接测试时却震精的发现,cq不支持11gR2.
l 于是准备重新升级至10g,并着手准备。但肖飒告知,之前升级过多次,每次导出导入到新库后,cq都无法录入缺陷,而且不知道什么原因。
l 考虑rman异机恢复,不使用exp,但是担心备份、搭建环境、异机恢复的过程较长,而且恢复后不一定能用,放弃异机恢复。
l 决定仍然使用该库,不过需要对该库大清洗,14号数据文件所在的表空间保存了大量数据,该表空间共8个数据文件,其中有5个已经快逼近4G,未来损坏的隐患很大,考虑到不能升级,决定将该表空间重建,摒弃大文件,共使用了13个1.9G的数据文件来接收迁移的段,而且10M增长。迁移中处理各种报错、约束等问题,迁移完后将原表空间和数据文件删除,顺便把表和索引碎片、高水位线问题解决了。共花了1天半时间,服务器太慢。
l 经测试cq登录正常,没有数据丢失。
介质恢复失败,所以依靠备份来恢复是不可能的,
RMAN> run{ 2> restore datafile 14; 3> recover datafile 14; 4> sql 'alter database datafile 14 online'; 5> } 启动 restore 于 2013-08-29 18:42:45 正在使用目标数据库控制文件替代恢复目录 分配的通道: ORA_DISK_1 通道 ORA_DISK_1: sid=14 devtype=DISK 通道 ORA_DISK_1: 正在开始恢复数据文件备份集 通道 ORA_DISK_1: 正在指定从备份集恢复的数据文件 正将数据文件00014恢复到D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF 通道 ORA_DISK_1: 已恢复备份段 1 段 handle=D:\CQ_BACKUP\DISK1\BAK_45OIH7KG_1_1 tag=TAG20130829T160016 params=NULL 通道 ORA_DISK_1: 恢复完成 完成 restore 于 2013-08-29 19:16:08 启动 recover 于 2013-08-29 19:16:08 使用通道 ORA_DISK_1 正在开始介质的恢复 无法恢复介质 RMAN-00571: =========================================================== RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS =============== RMAN-00571: =========================================================== RMAN-03002: failure of recover command at 08/29/2013 19:16:21 ORA-00283: recovery session canceled due to errors RMAN-11003: failure during parse/execution of SQL statement: alter database recover if needed datafile 14 ORA-00283: 恢复会话因错误而取消 ORA-01115: 从文件 14 读取块时出现 IO 错误 (块 # 502078) ORA-01110: 数据文件 14: 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF' ORA-27069: skgfdisp: 尝试在文件范围外执行 I/O OSD-04026: 传递的参数无效。 (OS 502078)
其实此时数据文件是好的,只是介质恢复时,有对数据文件范围外的地址进行读写,导致oracle无法访问而报错,因为dbv检查并没有坏块,所以不进行介质恢复,将14号文件先restore出来:
RMAN> restore datafile 14; 启动 restore 于 2013-08-29 19:16:49 使用通道 ORA_DISK_1 通道 ORA_DISK_1: 正在开始恢复数据文件备份集 通道 ORA_DISK_1: 正在指定从备份集恢复的数据文件 正将数据文件00014恢复到D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF 通道 ORA_DISK_1: 已恢复备份段 1 段 handle=D:\CQ_BACKUP\DISK1\BAK_45OIH7KG_1_1 tag=TAG20130829T160016 params=NULL 通道 ORA_DISK_1: 恢复完成 完成 restore 于 2013-08-29 19:54:21
将其offline后open,查询scn:
SQL> select checkpoint_change# from v$datafile; CHECKPOINT_CHANGE# ------------------ 432908646 432908646 432908646 432908646 432908646 432908646 432908646 432908646 432908646 432908646 432908646 CHECKPOINT_CHANGE# ------------------ 432908646 432908646 432893942 432908646 432908646 432908646 432908646 432908646 432908646 已选择20行。 SQL> select change# from v$recover_file; CHANGE# ---------- 432893942
14号文件的scn为432893942,而正常文件的scn是432908646,基于前面的推测,我断定这个文件只是header不一致,数据文件并无损坏,只是对该文件进行了超出控制范围外地址的读写而已,所以想使用隐含参数直接打开库,忽略一致性检查,但是最终失败。
因此果断直接使用bbed修改数据文件头,绕过介质恢复。
首先关库,TBS_CQSCHEMA_USE_02.DBF文件(14号坏文件)的1块信息:
struct kcvfh, 360 bytes @0 struct kcvfhbfh, 20 bytes @0 ub1 type_kcbh @0 0x0b ub1 frmt_kcbh @1 0x02 ub1 spare1_kcbh @2 0x00 ub1 spare2_kcbh @3 0x00 ub4 rdba_kcbh @4 0x03800001 ub4 bas_kcbh @8 0x00000000 ub2 wrp_kcbh @12 0x0000 ub1 seq_kcbh @14 0x01 ub1 flg_kcbh @15 0x04 (KCBHFC ub2 chkval_kcbh @16 0x1be2 ub2 spare3_kcbh @18 0x0000 struct kcvfhhdr, 76 bytes @20 ub4 kccfhswv @20 0x09200000 ub4 kccfhcvn @24 0x08000000 ub4 kccfhdbi @28 0x8a4b9dc5 text kccfhdbn[0] @32 D text kccfhdbn[1] @33 S text kccfhdbn[2] @34 _ text kccfhdbn[3] @35 T text kccfhdbn[4] @36 H text kccfhdbn[5] @37 C text kccfhdbn[6] @38 Q text kccfhdbn[7] @39 ub4 kccfhcsq @40 0x00003061 ub4 kccfhfsz @44 0x0007c000 s_blkz kccfhbsz @48 0x00 ub2 kccfhfno @52 0x000e ub2 kccfhtyp @54 0x0003 ub4 kccfhacid @56 0x00000000 ub4 kccfhcks @60 0x00000000 text kccfhtag[0] @64 text kccfhtag[1] @65 text kccfhtag[2] @66 text kccfhtag[3] @67 text kccfhtag[4] @68 text kccfhtag[5] @69 text kccfhtag[6] @70 text kccfhtag[7] @71 text kccfhtag[8] @72 text kccfhtag[9] @73 text kccfhtag[10] @74 text kccfhtag[11] @75 text kccfhtag[12] @76 text kccfhtag[13] @77 text kccfhtag[14] @78 text kccfhtag[15] @79 text kccfhtag[16] @80 text kccfhtag[17] @81 text kccfhtag[18] @82 text kccfhtag[19] @83 text kccfhtag[20] @84 text kccfhtag[21] @85 text kccfhtag[22] @86 text kccfhtag[23] @87 text kccfhtag[24] @88 text kccfhtag[25] @89 text kccfhtag[26] @90 text kccfhtag[27] @91 text kccfhtag[28] @92 text kccfhtag[29] @93 text kccfhtag[30] @94 text kccfhtag[31] @95 ub4 kcvfhrdb @96 0x00000000 struct kcvfhcrs, 8 bytes @100 ub4 kscnbas @100 0x127c90e6 ub2 kscnwrp @104 0x0000 ub4 kcvfhcrt @108 0x2eb8d8e1 ub4 kcvfhrlc @112 0x3128954b struct kcvfhrls, 8 bytes @116 ub4 kscnbas @116 0x19cd392a ub2 kscnwrp @120 0x0000 ub4 kcvfhbti @124 0x00000000 struct kcvfhbsc, 8 bytes @128 ub4 kscnbas @128 0x00000000 ub2 kscnwrp @132 0x0000 ub2 kcvfhbth @136 0x0000 ub2 kcvfhsta @138 0x0000 (NONE struct kcvfhckp, 36 bytes @140 struct kcvcpscn, 8 bytes @140 ub4 kscnbas @140 0x19cd6ff6 -- ub2 kscnwrp @144 0x0000 ub4 kcvcptim @148 0x31289e91 ub2 kcvcpthr @152 0x0001 union u, 12 bytes @156 struct kcvcprba, 12 bytes @156 ub4 kcrbaseq @156 0x00000003 ub4 kcrbabno @160 0x00000002 ub2 kcrbabof @164 0x0010 struct kcvcptr, 12 bytes @156 struct kcrtrscn, 8 bytes @156 ub4 kscnbas @156 0x00000003 ub2 kscnwrp @160 0x0002 ub4 kcrtrtim @164 0x5f540010 ub1 kcvcpetb[0] @168 0x02 ub1 kcvcpetb[1] @169 0x00 ub1 kcvcpetb[2] @170 0x00 ub1 kcvcpetb[3] @171 0x00 ub1 kcvcpetb[4] @172 0x00 ub1 kcvcpetb[5] @173 0x00 ub1 kcvcpetb[6] @174 0x00 ub1 kcvcpetb[7] @175 0x00 ub4 kcvfhcpc @176 0x00000381 ub4 kcvfhrts @180 0x3128945b ub4 kcvfhccc @184 0x00000380 struct kcvfhbcp, 36 bytes @188 struct kcvcpscn, 8 bytes @188 ub4 kscnbas @188 0x00000000 ub2 kscnwrp @192 0x0000 ub4 kcvcptim @196 0x00000000 ub2 kcvcpthr @200 0x0000 union u, 12 bytes @204 struct kcvcprba, 12 bytes @204 ub4 kcrbaseq @204 0x00000000 ub4 kcrbabno @208 0x00000000 ub2 kcrbabof @212 0x0000 struct kcvcptr, 12 bytes @204 struct kcrtrscn, 8 bytes @204 ub4 kscnbas @204 0x00000000 ub2 kscnwrp @208 0x0000 ub4 kcrtrtim @212 0x00000000 ub1 kcvcpetb[0] @216 0x00 ub1 kcvcpetb[1] @217 0x00 ub1 kcvcpetb[2] @218 0x00 ub1 kcvcpetb[3] @219 0x00 ub1 kcvcpetb[4] @220 0x00 ub1 kcvcpetb[5] @221 0x00 ub1 kcvcpetb[6] @222 0x00 ub1 kcvcpetb[7] @223 0x00 ub4 kcvfhbhz @224 0x00000000 struct kcvfhxcd, 16 bytes @228 ub4 space_kcvmxcd[0] @228 0x00000000 ub4 space_kcvmxcd[1] @232 0x00000000 ub4 space_kcvmxcd[2] @236 0x00000000 ub4 space_kcvmxcd[3] @240 0x00000000 word kcvfhtsn @244 14 ub2 kcvfhtln @248 0x0010 text kcvfhtnm[0] @250 T text kcvfhtnm[1] @251 B text kcvfhtnm[2] @252 S text kcvfhtnm[3] @253 _ text kcvfhtnm[4] @254 C text kcvfhtnm[5] @255 Q text kcvfhtnm[6] @256 S text kcvfhtnm[7] @257 C text kcvfhtnm[8] @258 H text kcvfhtnm[9] @259 E text kcvfhtnm[10] @260 M text kcvfhtnm[11] @261 A text kcvfhtnm[12] @262 _ text kcvfhtnm[13] @263 U text kcvfhtnm[14] @264 S text kcvfhtnm[15] @265 E text kcvfhtnm[16] @266 text kcvfhtnm[17] @267 text kcvfhtnm[18] @268 text kcvfhtnm[19] @269 text kcvfhtnm[20] @270 text kcvfhtnm[21] @271 text kcvfhtnm[22] @272 text kcvfhtnm[23] @273 text kcvfhtnm[24] @274 text kcvfhtnm[25] @275 text kcvfhtnm[26] @276 text kcvfhtnm[27] @277 text kcvfhtnm[28] @278 text kcvfhtnm[29] @279 ub4 kcvfhrfn @280 0x0000000e struct kcvfhrfs, 8 bytes @284 ub4 kscnbas @284 0x00000000 ub2 kscnwrp @288 0x0000 ub4 kcvfhrft @292 0x00000000 struct kcvfhafs, 8 bytes @296 ub4 kscnbas @296 0x00000000 ub2 kscnwrp @300 0x0000 ub4 kcvfhbbc @304 0x00000000 ub4 kcvfhncb @308 0x00000000 ub4 kcvfhmcb @312 0x00000000 ub4 kcvfhlcb @316 0x00000000 ub4 kcvfhbcs @320 0x00000000 ub2 kcvfhofb @324 0x0000 ub2 kcvfhnfb @326 0x0000 ub4 kcvfhprc @328 0x00000000 struct kcvfhprs, 8 bytes @332 ub4 kscnbas @332 0x00000000 ub2 kscnwrp @336 0x0000 struct kcvfhprfs, 8 bytes @340 ub4 kscnbas @340 0x00000000 ub2 kscnwrp @344 0x0000 ub4 kcvfhtrt @356 0x00000000
找一个好的数据文件,同样print一下:
struct kcvfh, 360 bytes @0 struct kcvfhbfh, 20 bytes @0 ub1 type_kcbh @0 0x0b ub1 frmt_kcbh @1 0x02 ub1 spare1_kcbh @2 0x00 ub1 spare2_kcbh @3 0x00 ub4 rdba_kcbh @4 0x04c00001 ub4 bas_kcbh @8 0x00000000 ub2 wrp_kcbh @12 0x0000 ub1 seq_kcbh @14 0x01 ub1 flg_kcbh @15 0x04 (KCBHFCK ub2 chkval_kcbh @16 0xe33e ub2 spare3_kcbh @18 0x0000 struct kcvfhhdr, 76 bytes @20 ub4 kccfhswv @20 0x09200000 ub4 kccfhcvn @24 0x08000000 ub4 kccfhdbi @28 0x8a4b9dc5 text kccfhdbn[0] @32 D text kccfhdbn[1] @33 S text kccfhdbn[2] @34 _ text kccfhdbn[3] @35 T text kccfhdbn[4] @36 H text kccfhdbn[5] @37 C text kccfhdbn[6] @38 Q text kccfhdbn[7] @39 ub4 kccfhcsq @40 0x00003134 ub4 kccfhfsz @44 0x0000fa00 s_blkz kccfhbsz @48 0x00 ub2 kccfhfno @52 0x0013 ub2 kccfhtyp @54 0x0003 ub4 kccfhacid @56 0x00000000 ub4 kccfhcks @60 0x00000000 text kccfhtag[0] @64 text kccfhtag[1] @65 text kccfhtag[2] @66 text kccfhtag[3] @67 text kccfhtag[4] @68 text kccfhtag[5] @69 text kccfhtag[6] @70 text kccfhtag[7] @71 text kccfhtag[8] @72 text kccfhtag[9] @73 text kccfhtag[10] @74 text kccfhtag[11] @75 text kccfhtag[12] @76 text kccfhtag[13] @77 text kccfhtag[14] @78 text kccfhtag[15] @79 text kccfhtag[16] @80 text kccfhtag[17] @81 text kccfhtag[18] @82 text kccfhtag[19] @83 text kccfhtag[20] @84 text kccfhtag[21] @85 text kccfhtag[22] @86 text kccfhtag[23] @87 text kccfhtag[24] @88 text kccfhtag[25] @89 text kccfhtag[26] @90 text kccfhtag[27] @91 text kccfhtag[28] @92 text kccfhtag[29] @93 text kccfhtag[30] @94 text kccfhtag[31] @95 ub4 kcvfhrdb @96 0x00000000 struct kcvfhcrs, 8 bytes @100 ub4 kscnbas @100 0x19504563 ub2 kscnwrp @104 0x0000 ub4 kcvfhcrt @108 0x30f78f0e ub4 kcvfhrlc @112 0x3128954b struct kcvfhrls, 8 bytes @116 ub4 kscnbas @116 0x19cd392a ub2 kscnwrp @120 0x0000 ub4 kcvfhbti @124 0x00000000 struct kcvfhbsc, 8 bytes @128 ub4 kscnbas @128 0x00000000 ub2 kscnwrp @132 0x0000 ub2 kcvfhbth @136 0x0000 ub2 kcvfhsta @138 0x0000 (NONE) struct kcvfhckp, 36 bytes @140 struct kcvcpscn, 8 bytes @140 ub4 kscnbas @140 0x19cda316 ub2 kscnwrp @144 0x0000 ub4 kcvcptim @148 0x3128c136 ub2 kcvcpthr @152 0x0001 union u, 12 bytes @156 struct kcvcprba, 12 bytes @156 ub4 kcrbaseq @156 0x00000004 ub4 kcrbabno @160 0x000020b9 ub2 kcrbabof @164 0x0010 struct kcvcptr, 12 bytes @156 struct kcrtrscn, 8 bytes @156 ub4 kscnbas @156 0x00000004 ub2 kscnwrp @160 0x20b9 ub4 kcrtrtim @164 0x03970010 ub1 kcvcpetb[0] @168 0x02 ub1 kcvcpetb[1] @169 0x00 ub1 kcvcpetb[2] @170 0x00 ub1 kcvcpetb[3] @171 0x00 ub1 kcvcpetb[4] @172 0x00 ub1 kcvcpetb[5] @173 0x00 ub1 kcvcpetb[6] @174 0x00 ub1 kcvcpetb[7] @175 0x00 ub4 kcvfhcpc @176 0x000000bb ub4 kcvfhrts @180 0x3128b5d6 ub4 kcvfhccc @184 0x000000ba struct kcvfhbcp, 36 bytes @188 struct kcvcpscn, 8 bytes @188 ub4 kscnbas @188 0x00000000 ub2 kscnwrp @192 0x0000 ub4 kcvcptim @196 0x00000000 ub2 kcvcpthr @200 0x0000 union u, 12 bytes @204 struct kcvcprba, 12 bytes @204 ub4 kcrbaseq @204 0x00000000 ub4 kcrbabno @208 0x00000000 ub2 kcrbabof @212 0x0000 struct kcvcptr, 12 bytes @204 struct kcrtrscn, 8 bytes @204 ub4 kscnbas @204 0x00000000 ub2 kscnwrp @208 0x0000 ub4 kcrtrtim @212 0x00000000 ub1 kcvcpetb[0] @216 0x00 ub1 kcvcpetb[1] @217 0x00 ub1 kcvcpetb[2] @218 0x00 ub1 kcvcpetb[3] @219 0x00 ub1 kcvcpetb[4] @220 0x00 ub1 kcvcpetb[5] @221 0x00 ub1 kcvcpetb[6] @222 0x00 ub1 kcvcpetb[7] @223 0x00 ub4 kcvfhbhz @224 0x00000000 struct kcvfhxcd, 16 bytes @228 ub4 space_kcvmxcd[0] @228 0x00000000 ub4 space_kcvmxcd[1] @232 0x00000000 ub4 space_kcvmxcd[2] @236 0x00000000 ub4 space_kcvmxcd[3] @240 0x00000000 word kcvfhtsn @244 14 ub2 kcvfhtln @248 0x0010 text kcvfhtnm[0] @250 T text kcvfhtnm[1] @251 B text kcvfhtnm[2] @252 S text kcvfhtnm[3] @253 _ text kcvfhtnm[4] @254 C text kcvfhtnm[5] @255 Q text kcvfhtnm[6] @256 S text kcvfhtnm[7] @257 C text kcvfhtnm[8] @258 H text kcvfhtnm[9] @259 E text kcvfhtnm[10] @260 M text kcvfhtnm[11] @261 A text kcvfhtnm[12] @262 _ text kcvfhtnm[13] @263 U text kcvfhtnm[14] @264 S text kcvfhtnm[15] @265 E text kcvfhtnm[16] @266 text kcvfhtnm[17] @267 text kcvfhtnm[18] @268 text kcvfhtnm[19] @269 text kcvfhtnm[20] @270 text kcvfhtnm[21] @271 text kcvfhtnm[22] @272 text kcvfhtnm[23] @273 text kcvfhtnm[24] @274 text kcvfhtnm[25] @275 text kcvfhtnm[26] @276 text kcvfhtnm[27] @277 text kcvfhtnm[28] @278 text kcvfhtnm[29] @279 ub4 kcvfhrfn @280 0x00000013 struct kcvfhrfs, 8 bytes @284 ub4 kscnbas @284 0x00000000 ub2 kscnwrp @288 0x0000 ub4 kcvfhrft @292 0x3128ac64 struct kcvfhafs, 8 bytes @296 ub4 kscnbas @296 0x00000000 ub2 kscnwrp @300 0x0000 ub4 kcvfhbbc @304 0x00000000 ub4 kcvfhncb @308 0x00000000 ub4 kcvfhmcb @312 0x00000000 ub4 kcvfhlcb @316 0x00000000 ub4 kcvfhbcs @320 0x00000000 ub2 kcvfhofb @324 0x0000 ub2 kcvfhnfb @326 0x0000 ub4 kcvfhprc @328 0x00000000 struct kcvfhprs, 8 bytes @332 ub4 kscnbas @332 0x00000000 ub2 kscnwrp @336 0x0000 struct kcvfhprfs, 8 bytes @340 ub4 kscnbas @340 0x00000000 ub2 kscnwrp @344 0x0000 ub4 kcvfhtrt @356 0x00000000
此处简单的解释一下,以上信息就是数据文件头部第一个block的信息,这360个字节存储了数据文件至关重要的一些信息,如32到第39共8个字节存储的是实例名(9i最大支持8个字符?),第250-279字节存储的是表空间名,可见是30个字节,的确,9i的表空间名最大只支持30个字符。以下是关键信息:
ub4 kscnbas @140 0x19cdab15(432909077) ub4 kcvcptim @148 0x3128df56 ub4 kcvfhcpc @176 0x000000bf ub4 kcvfhccc @184 0x000000be
当open的时候,smon会检查数据文件的以上信息是否和控制文件中的一致,如果不一致,这个文件就需要恢复,实际上一方面恢复数据,如撤销或者重做事务;一方面一致文件头等,否则这个文件就进入recover状态无法读取也无法open。我下面要做的就是手动修改这些字节区间的数据,将其同步,骗过smon进程打开文件。
对比损坏文件的头信息:
ub4 kscnbas @140 0x19cd6ff6--432893942 ub4 kcvcptim @148 0x31289e91 ub4 kcvfhcpc @176 0x00000381 ub4 kcvfhccc @184 0x00000380
修改之前,我需要确认正常的文件中,数据是如何存储的:
d /v dba 14,1 offset 140 count 16 File: D:\oracle\oradata\DS_THCQ\TBS_CQSCHEMA_USE_06.DBF (14) Block: 1 Offsets: 140 to 155 Dba:0x03800001 ------------------------------------------------------- 15abcd19 00000000 56df2831 01000000 l ........V.(1.... <16 bytes per line>
由此可看出,在140个偏移处,scn其实是0x19cdab15,但是存储居然是15abcd19 ,看到不同了吗?是反向存储的(因为低位的字节存储在内存中的低地址处),注意15abcd19 是16进制,一位4bit,2位代表一个字节,共存储4个字节。同样可以看出,oracle中的scn的最大值是ffffffffffff,大小正好是6字节,48个bit,后面的2字节没有用到可能是留着扩展吧?很有趣吧?这就是oracle的最低层的存储结构啦。
下面进行修改:
BBED> modify /x 15abcd19 dba 14,1 offset 140 File: D:\oracle\oradata\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF (14) Block: 1 Offsets: 140 to 651 Dba:0x03800001 ------------------------------------------------------------------------ 15abcd19 00000000 919e2831 01000000 03000000 02000000 1000545f 02000000 00000000 81030000 5b942831 80030000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0e000000 10005442 535f4351 53434845 4d415f55 53450000 00000000 00000000 00000000 0e000000 00000000 00000000 00000000 00000000 0000505f 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <32 bytes per line> BBED> modify /x 56df2831 dba 14,1 offset 148 File: D:\oracle\oradata\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF (14) Block: 1 Offsets: 148 to 659 Dba:0x03800001 ------------------------------------------------------------------------ 56df2831 01000000 03000000 02000000 1000545f 02000000 00000000 81030000 5b942831 80030000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0e000000 10005442 535f4351 53434845 4d415f55 53450000 00000000 00000000 00000000 0e000000 00000000 00000000 00000000 00000000 0000505f 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <32 bytes per line> BBED> modify /x bf dba 14,1 offset 176 File: D:\oracle\oradata\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF (14) Block: 1 Offsets: 176 to 687 Dba:0x03800001 ------------------------------------------------------------------------ bf030000 5b942831 80030000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0e000000 10005442 535f4351 53434845 4d415f55 53450000 00000000 00000000 00000000 0e000000 00000000 00000000 00000000 00000000 0000505f 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <32 bytes per line> BBED> modify /x b3 dba 14,1 offset 184 File: D:\oracle\oradata\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF (14) Block: 1 Offsets: 184 to 695 Dba:0x03800001 ------------------------------------------------------------------------ b3030000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0e000000 10005442 535f4351 53434845 4d415f55 53450000 00000000 00000000 00000000 0e000000 00000000 00000000 00000000 00000000 0000505f 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <32 bytes per line>
修改完成后保存校验一下,然后打开库:
SQL> shu immediate 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 SQL> startup mount ORACLE 例程已经启动。 Total System Global Area 1368466872 bytes Fixed Size 456120 bytes Variable Size 713031680 bytes Database Buffers 654311424 bytes Redo Buffers 667648 bytes 数据库装载完毕。 SQL> alter database datafile 14 online; 数据库已更改。 SQL> alter database open; alter database open * ERROR 位于第 1 行: ORA-01122: 数据库文件 14 验证失败 ORA-01110: 数据文件 14: 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF' ORA-01207: 文件比控制文件更新 - 旧的控制文件
由于14号文件一直无法online,所以控制文件中的检查点是旧的,smon此时发现这个数据文件太超前了 ,也不能打开,分析后决定重建控制文件。重建后无需recover,直接open即可:
SQL> shu abort ORACLE 例程已经关闭。 SQL> startup nomount; ORACLE 例程已经启动。 Total System Global Area 1368466872 bytes Fixed Size 456120 bytes Variable Size 713031680 bytes Database Buffers 654311424 bytes Redo Buffers 667648 bytes SQL> CREATE CONTROLFILE REUSE DATABASE "DS_THCQ" NORESETLOGS 2 -- SET STANDBY TO MAXIMIZE PERFORMANCE 3 MAXLOGFILES 50 4 MAXLOGMEMBERS 5 5 MAXDATAFILES 100 6 MAXINSTANCES 1 7 MAXLOGHISTORY 453 8 LOGFILE 9 GROUP 1 'D:\ORACLE\ORADATA\DS_THCQ\REDO01.LOG' SIZE 10 GROUP 2 'D:\ORACLE\ORADATA\DS_THCQ\REDO02.LOG' SIZE 11 GROUP 3 'D:\ORACLE\ORADATA\DS_THCQ\REDO03.LOG' SIZE 12 -- STANDBY LOGFILE 13 DATAFILE 14 'D:\ORACLE\ORADATA\DS_THCQ\SYSTEM01.DBF', 15 'D:\ORACLE\ORADATA\DS_THCQ\UNDOTBS01.DBF', 16 'D:\ORACLE\ORADATA\DS_THCQ\CWMLITE01.DBF', 17 'D:\ORACLE\ORADATA\DS_THCQ\DRSYS01.DBF', 18 'D:\ORACLE\ORADATA\DS_THCQ\EXAMPLE01.DBF', 19 'D:\ORACLE\ORADATA\DS_THCQ\INDX01.DBF', 20 'D:\ORACLE\ORADATA\DS_THCQ\ODM01.DBF', 21 'D:\ORACLE\ORADATA\DS_THCQ\TOOLS01.DBF', 22 'D:\ORACLE\ORADATA\DS_THCQ\USERS01.DBF', 23 'D:\ORACLE\ORADATA\DS_THCQ\XDB01.DBF', 24 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQMODEL.ORA', 25 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_01.DBF', 26 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_01.DBF', 27 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_02.DBF', 28 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_03.DBF', 29 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_04.DBF', 30 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_05.DBF', 31 'D:\ORACLE\ORADATA\DS_THCQ\TBS_STATS.DBF', 32 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_06.DBF', 33 'D:\ORACLE\ORADATA\DS_THCQ\TBS_CQSCHEMA_USE_08.DBF' 34 CHARACTER SET ZHS16GBK 35 ; 控制文件已创建 SQL> RECOVER DATABASE ORA-00283: ?????????? ORA-00264: ????? SQL> alter database open; 数据库已更改。
由此也看出,oracle的数据文件其实没什么神秘的,也不过是按照自己的规则存储的一些二进制数据,而且都是明文未加密的。
1号块供8KB的空间可以存储很多数据,了解了1号块的数据结构后,通过修改诸如实例名,表空间名、数据头等信息,可以将任何一个库的任何一个时期的任何文件挂到其他的库上打开,说不定还能读出数据。oracle的sga其实就是一个大的阅读器而已。
其实这和外部表是很相似的,外部表其实就是没有data header的数据文件而已,oracle在读之前并不判断该文件是否有效合法,以高度容错性的方法去读取;而标准的dbf文件则不是,Oracle读取之前要经过严格的校验和检查,有一点不对的地方都认为它是损坏的。而通过对header进行修复甚至伪造即可以骗过oracle去读取。
所以,其实能允许一定的数据丢失的话,其实没有备份也是可以将数据文件一致并打开的,这可以用于数据库无备份时的灾难恢复抢救数据,如本案例。
而且如直接修改数据,修复坏块,撤销删除的数据等,包括本案例直接修改文件头等块级操作都可以实现,如果熟悉oracle底层存储结构的话自己写程序修改都不是难事。