您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息
三六零分类信息网 > 海口分类信息网,免费分类信息发布

一次Oracle数据恢复实践

2024/3/5 19:33:11发布25次查看
系统的维护人员称是星期五出的错,发现出错是在星期天,也就是我恢复数据的日期,与声称的出错时间已经隔了将近2天。开始尝试用f
本文简单记录一下最近一次数据恢复的过程。
事情的起因是,一个应用升级后,某一个操作导致一个表的几个列全部被更新为同一值(忍不住又要唠叨测试的重要性)。这样的错误居然出现在应用代码中,显然是重大的bug。那个是罪魁祸首的sql,update语句,其where条件仅仅只有一个where 1=1。
系统的维护人员称是星期五出的错,发现出错是在星期天,也就是我恢复数据的日期,与声称的出错时间已经隔了将近2天。开始尝试用flashback query恢复数据,报ora-01555错误,此路不通。维护人员说,星期五之前的rman备份已经被删除了(又是一个备份恢复策略不当地例子),使用基于时间点的恢复也不可能了。剩下的一条路,,只有使用log miner。还好归档文件还在数据库服务器上。
这套库是一套rac数据库,由于没有人能确认操作发生在哪个节点,因此需要将一个节点下所有的归档复制到另一个节点上(如果没有足够的空间,可以使用nfs)。然后需要找到我们用于数据恢复的归档日志:
set linesize 170 pagesize 10000alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';col name for a30col first_change for a10col next_change for a10select max(first_time) from v$archived_logwhere first_time =to_date('200909251707','yyyymmddhh24mi')order by 2;--这里的时间为前一sql的max(first_time)结果 sequence# first_time          name                           first_chan next_chang---------- ------------------- ------------------------------ ---------- ----------      4039 2009-09-25 17:07:10 /arch/db1_1_4039.arc          88ce7eff   88d1457c      4040 2009-09-26 12:24:52 /arch/db1_1_4040.arc          88d1457c   88d1459f      4041 2009-09-26 12:25:22 /arch/db1_1_4041.arc          88d1459f   88d156a4      4688 2009-09-26 12:37:59 /arch/db1_2_4688.arc          88d1457f   88d1464a      4689 2009-09-26 12:38:27 /arch/db1_2_4689.arc          88d1464a   88d1569c      4042 2009-09-26 12:54:44 /arch/db1_1_4042.arc          88d156a4   88d157e7      4043 2009-09-26 12:54:56 /arch/db1_1_4043.arc          88d157e7   88d1ab06      4690 2009-09-26 13:07:47 /arch/db1_2_4690.arc          88d1569c   88d1570b      4691 2009-09-26 13:08:00 /arch/db1_2_4691.arc          88d1570b   88d1ab09      4044 2009-09-26 15:27:32 /arch/db1_1_4044.arc          88d1ab06   88d1ab0d      4045 2009-09-26 15:27:35 /arch/db1_1_4045.arc          88d1ab0d   88d25091      4692 2009-09-26 15:40:36 /arch/db1_2_4692.arc          88d1ab09   88d1ab77      4693 2009-09-26 15:40:39 /arch/db1_2_4693.arc          88d1ab77   88d25094      4046 2009-09-26 22:24:07 /arch/db1_1_4046.arc          88d25091   88d250db      4047 2009-09-26 22:24:19 /arch/db1_1_4047.arc          88d250db   88d2515e      4048 2009-09-26 22:24:29 /arch/db1_1_4048.arc          88d2515e   88d25167      4049 2009-09-26 22:24:41 /arch/db1_1_4049.arc          88d25167   88d25cac      4694 2009-09-26 22:37:13 /arch/db1_2_4694.arc          88d25094   88d25147      4695 2009-09-26 22:37:25 /arch/db1_2_4695.arc          88d25147   88d2515b      4696 2009-09-26 22:37:33 /arch/db1_2_4696.arc          88d2515b   88d2516a      4697 2009-09-26 22:37:47 /arch/db1_2_4697.arc          88d2516a   88d25ca9      4050 2009-09-26 22:41:57 /arch/db1_1_4050.arc          88d25cac   88d25cde      4698 2009-09-26 22:55:01 /arch/db1_2_4698.arc          88d25ca9   88d25dcf      4699 2009-09-26 22:55:19 /arch/db1_2_4699.arc          88d25dcf   88dbd27e尝试找到数据被错误更新的时间点:
exec sys.dbms_logmnr.add_logfile(logfilename=>'/arch/db1_1_4038.arc');exec sys.dbms_logmnr.add_logfile(logfilename=>'/arch/db1_1_4039.arc');exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog);col sql_redo for a50select scn,timestamp,username,sql_redo from v$logmnr_contentswhere operation='update' and upper(sql_redo) like '%tbl_form_form%'and sql_redo like '%sgs0900021bnc10%' --这个值是update时某一列被更新后的值,用在这里便于查找。order by scn,timestamp;exec sys.dbms_logmnr.end_logmnr;很不幸的是,没有找着需要的数据。再往后找了几个日志,也没找着。
如果一直找下去,显然会消耗比较长的时间,业务也已经停止了。不过可以用一种简单的方法来查找数据被错误更新发生的时间:一个比较大的表,通常段头后面的那个块,也就是存储那个表的数据的第1个块,通常是很少更新的,至少当时恢复的那个表是这样一种情况。我们可以通过数据块中itl上的事务scn来满足我们的要求。
sql> select tablespace_name,extent_id,file_id,block_id,blocks     from dba_extents where owner='xxx'     and segment_name='tbl_form_form'     order by extent_id;tablespace_name   extent_id    file_id   block_id  blocks---------------- ---------- ---------- ---------- -------xxxx                      0         16      25481     128xxxx                      1         17      23433     128xxxx                      2         18      21385     128xxxx                      3         19      19977     128xxxx                      4         16      23945     128xxxx                      5         17       8585     128xxxx                      6         18      14217     128xxxx                      7         19      18825     128sql> alter system dump datafile 16 block 25482;system altered.start dump data blocks tsn: 4 file#: 16 minblk 25482 maxblk 25482buffer tsn: 4 rdba: 0x0400638a (16/25482)scn: 0x0000.88e21027 seq: 0x02 flg: 0x00 tail: 0x10270602frmt: 0x02 chkval: 0x0000 type: 0x06=trans datablock header dump:  0x0400638a object id on block? y seg/obj: 0x40d8  csc: 0x00.88e20c40  itc: 2  flg: -  typ: 1 - data     fsl: 0  fnx: 0x0 ver: 0x01 itl           xid                  uba         flag  lck        scn/fsc0x01   0x0010.011.0006ed74  0x03c002a0.2f48.07  c---    0  scn 0x0000.88d7af300x02   0x0012.019.000027e0  0x03c00ede.05de.42  c---    0  scn 0x0000.44e2ee39从上面的结果可以看到,数据块的itl中,最新的事务其scn为88d7af30,正处于最后一个归档日志的first_change#和last_change#之间,即88d25dcf和88dbd27e之间,难不成这个错误是今天早上才发生的?于是我挖掘最后1个归档日志,结果发生错误的确是发生在早上,也就是我开始进行恢复操作之前半个小时。
既然错误并没有发生太久,同时这个系统也允许一定的数据丢失,那就使用flashback query,得到update操作之前的数据即可。
create table tbl_form_form_newas select * from tbl_form_formas of timestamp to_date('2009-09-27 09:08:00','yyyy-mm-dd hh24:mi:ss');--当然这里也可以按scn进行闪回。幸运的是,这次闪回查询成功了。看起来足够大的undo表空间还是有好处,至少我已经有数次用闪回查询来恢复数据。
海口分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录