不小心删表删库了,还能救
前言
常在河邊走,哪能不濕鞋?
今天有客戶聯(lián)系說誤更新數(shù)據(jù)表,導(dǎo)致數(shù)據(jù)錯亂了,希望將這張表恢復(fù)到?一周前?的指定時間點。
-
數(shù)據(jù)庫版本為?11.2.0.1
-
操作系統(tǒng)是?Windows64
-
數(shù)據(jù)已經(jīng)被更改超過1周時間
-
數(shù)據(jù)庫已開啟歸檔模式
-
沒有DG容災(zāi)
-
有RMAN備份
下面模擬一下問題的詳細(xì)解決過程!
一、分析
以下只列出常規(guī)恢復(fù)手段:
-
數(shù)據(jù)已經(jīng)誤操作超過一周,所以排除使用UNDO快照來找回;
-
沒有DG容災(zāi)環(huán)境,排除使用DG閃回;
-
主庫已開啟歸檔模式,并且存在RMAN備份,可使用RMAN異機(jī)恢復(fù)表對應(yīng)表空間,使用DBLINK撈回數(shù)據(jù)表;
-
Oracle 12C后支持單張表恢復(fù);
結(jié)論:安全起見,使用RMAN異機(jī)恢復(fù)表空間來撈回數(shù)據(jù)表。
二、思路
客戶希望將表數(shù)據(jù)恢復(fù)到 <2021/06/08 17:00:00> 之前某個時間點。
大致操作步驟如下:
-
主庫查詢誤更新數(shù)據(jù)表對應(yīng)的表空間和無需恢復(fù)的表空間。
-
新主機(jī)安裝Oracle 11.2.0.1數(shù)據(jù)庫軟件,無需建庫,目錄結(jié)構(gòu)最好保持一致。
-
主庫拷貝參數(shù)文件,密碼文件至新主機(jī),根據(jù)新主機(jī)修改參數(shù)文件和創(chuàng)建新實例所需目錄。
-
新主機(jī)使用修改后的參數(shù)文件打開數(shù)據(jù)庫實例到nomount狀態(tài)。
-
主庫拷貝備份的控制文件至新主機(jī),新主機(jī)使用RMAN恢復(fù)控制文件,并且MOUNT新實例。
-
新主機(jī)RESTORE TABLESPACE恢復(fù)至?xí)r間點 ?<2021/06/08 16:00:00>。
-
新主機(jī)RECOVER DATABASE SKIP TABLESPACE恢復(fù)至?xí)r間點 ?<2021/06/08 16:00:00>。
-
新主機(jī)實例開啟到只讀模式。
-
確認(rèn)新主機(jī)實例的表數(shù)據(jù)是否正確,若不正確則重復(fù)?第7步?調(diào)整時間點慢慢往?<2021/06/08 ?17:00:00>?推進(jìn)恢復(fù)。
-
主庫創(chuàng)建連通新主機(jī)實例的DBLINK,通過DBLINK從新主機(jī)實例撈取表數(shù)據(jù)。
📢 注意:?選擇表空間恢復(fù)是因為主庫數(shù)據(jù)量比較大,如果全庫恢復(fù)需要大量時間。
三、測試環(huán)境模擬
為了數(shù)據(jù)脫敏,因此以測試環(huán)境模擬場景進(jìn)行演示!
?? 測試環(huán)境可以使用腳本安裝,可以使用博主編寫的 Oracle 一鍵安裝腳本,同時支持單機(jī)和 RAC 集群模式!
1、環(huán)境準(zhǔn)備
測試環(huán)境信息如下:
| 主庫 | rhel6.9 | orcl | orcl | 11.2.0.1 | 10.211.55.111 |
| 新主機(jī) | rhel6.9 | orcl | 不創(chuàng)建實例 | 11.2.0.1 | 10.211.55.112 |
2、模擬測試場景
主庫開啟歸檔模式:
sqlplus?/?as?sysdba ##?設(shè)置歸檔路徑 alter?system?set?log_archive_dest_1='LOCATION=/archivelog'; ##?重啟開啟歸檔模式 shutdown?immediate startup?mount alter database archivelog; ##?打開數(shù)據(jù)庫 alter?database?open;創(chuàng)建測試數(shù)據(jù):
sqlplus?/?as?sysdba ##?創(chuàng)建表空間 create?tablespace?lucifer?datafile?'/oradata/orcl/lucifer01.dbf'?size?10M?autoextend?off; create?tablespace?ltest?datafile?'/oradata/orcl/ltest01.dbf'?size?10M?autoextend?off; ##?創(chuàng)建用戶 create?user?lucifer?identified?by?lucifer; grant?dba?to?lucifer; ##?創(chuàng)建表 conn?lucifer/lucifer create?table?lucifer(id?number?not?null,name?varchar2(20))?tablespace?lucifer; ##?插入數(shù)據(jù) insert?into?lucifer?values(1,'lucifer'); insert?into?lucifer?values(2,'test1'); insert?into?lucifer?values(3,'test2'); commit;進(jìn)行數(shù)據(jù)庫全備:
rman?target?/ ##?進(jìn)入?rman?后執(zhí)行以下命令 run?{ allocate?channel?c1?device?type?disk; allocate?channel?c2?device?type?disk; crosscheck?backup; crosscheck?archivelog?all;? sql"alter?system?switch?logfile"; delete?noprompt?expired?backup; delete?noprompt?obsolete?device?type?disk; backup?database?include?current?controlfile?format?'/backup/backlv0_%d_%T_%t_%s_%p'; backup?archivelog?all?DELETE?INPUT; release?channel?c1; release?channel?c2; }模擬數(shù)據(jù)修改:
sqlplus?/?as?sysdba conn?lucifer/lucifer delete?from?lucifer?where?id=1; update?lucifer?set?name='lucifer'?where?id=2; commit;📢 注意:?為了模擬客戶環(huán)境,假設(shè)無法通過UNDO快照找回,當(dāng)前刪除時間點為:<2021/06/17 18:10:00>。
如果使用UNDO快照,比較方便:
sqlplus?/?as?sysdba ##?查找UNDO快照數(shù)據(jù)是否正確 select?*?from?lucifer.lucifer?as?of?timestamp?to_timestamp('2021-06-17?18:05:00','YYYY-MM-DD?HH24:MI:SS'); ##?將UNDO快照數(shù)據(jù)撈至新建表中 create?table?lucifer.lucifer_0617?as?select?*?from?lucifer.lucifer?as?of?timestamp?to_timestamp('2021-06-17?18:05:00','YYYY-MM-DD?HH24:MI:SS');四、RMAN完整恢復(fù)過程
主庫查詢誤更新數(shù)據(jù)表對應(yīng)的表空間和無需恢復(fù)的表空間:
sqlplus?/?as?sysdba ##?查詢誤更新數(shù)據(jù)表對應(yīng)表空間 select?owner,tablespace_name?from?dba_segments?where?segment_name='LUCIFER'; ##?查詢所有表空間 select?tablespace_name?from?dba_tablespaces;主庫拷貝參數(shù)文件,密碼文件至新主機(jī),根據(jù)新主機(jī)修改參數(shù)文件和創(chuàng)建新實例所需目錄:
##?生成pfile參數(shù)文件 sqlplus?/?as?sysdba create?pfile='/home/oracle/pfile.ora'?from?spfile; exit; ##?拷貝至新主機(jī) su?-?oracle scp?/home/oracle/pfile.ora?10.211.55.112:/tmp scp?$ORACLE_HOME/dbs/orapworcl?10.211.55.112:$ORACLE_HOME/dbs ##?新主機(jī)根據(jù)實際情況修改參數(shù)文件并且創(chuàng)建目錄 mkdir?-p?/u01/app/oracle/admin/orcl/adump mkdir?-p?/oradata/orcl/ mkdir?-p?/archivelog chown?-R?oracle:oinstall?/archivelog chown?-R?oracle:oinstall?/oradata新主機(jī)使用修改后的參數(shù)文件打開數(shù)據(jù)庫實例到nomount狀態(tài):
sqlplus?/?as?sysdba startup?nomount?pfile='/tmp/pfile.ora';主庫拷貝備份的控制文件至新主機(jī),新主機(jī)使用RMAN恢復(fù)控制文件,并且MOUNT新實例:
rman?target?/ list?backup?of?controlfile; exit; ##?拷貝備份文件至新主機(jī) scp?/backup/backlv0_ORCL_20210617_107548592*?10.211.55.112:/tmp scp?/u01/app/oracle/product/11.2.0/db/dbs/0c01l775_1_1?10.211.55.112:/tmp ##?新主機(jī)恢復(fù)控制文件并開啟到mount狀態(tài) rman?target?/ restore?controlfile?from?'/tmp/backlv0_ORCL_20210617_1075485924_9_1'; alter?database?mount;通過?list backup of controlfile;?可以看到控制文件位置:
新主機(jī)RESTORE TABLESPACE恢復(fù)至?xí)r間點?<2021/06/17 18:06:00>?:
##?新主機(jī)注冊備份集 rman?target?/ catalog?start?with?'/tmp/backlv0_ORCL_20210617_107548592'; crosscheck?backup; delete?noprompt?expired?backup; delete?noprompt?obsolete?device?type?disk; ##?恢復(fù)表空間LUCIFER和系統(tǒng)表空間,指定時間點?`2021/06/17?18:06:00` run?{ sql?'alter?session?set?nls_date_format="yyyy-mm-dd?hh24:mi:ss"'; set?until?time?'2021-06-17?18:06:00'; allocate?channel?ch01?device?type?disk; allocate?channel?ch02?device?type?disk; restore?tablespace?SYSTEM,SYSAUX,UNDOTBS1,USERS,LUCIFER; release?channel?ch01; release?channel?ch02; }新主機(jī)RECOVER DATABASE SKIP TABLESPACE恢復(fù)至?xí)r間點?<2021/06/17 18:06:00>?:
rman?target?/ run?{ sql?'alter?session?set?nls_date_format="yyyy-mm-dd?hh24:mi:ss"'; set?until?time?'2021-06-17?18:06:00'; allocate?channel?ch01?device?type?disk; recover?database?skip?tablespace?LTEST,EXAMPLE; release?channel?ch01; }這里有一個小BUG:?客戶環(huán)境是Windows,執(zhí)行這一步最后報錯,手動offline數(shù)據(jù)文件依然無法開啟數(shù)據(jù)庫。
解決方案:
sqlplus?/?as?sysdba ##?將恢復(fù)跳過的表空間都o(jì)ffline?drop掉,執(zhí)行以下查詢結(jié)果 select?'alter?database?datafile?'||?file_id?||'?offline?drop;'?from?dba_data_files?where?tablespace_name?in?('LTEST','EXAMPLE'); ##?再次開啟數(shù)據(jù)庫 alter?database?open?read?only;📢 注意:?如果顯示缺歸檔日志,可以參考如下步驟:
sqlplus?/?as?sysdba ##?查詢恢復(fù)需要的歸檔日志號時間? alter?session?set?nls_date_format="yyyy-mm-dd?hh24:mi:ss";? select?first_time,sequence#?from?v$archived_log?where?sequence#='7'; exit; ##?通過備份RESTORE吐出所需的歸檔日志? rman?target?/? catalog?start?with?'/tmp/0c01l775_1_1';? crosscheck?archivelog?all;? run?{? allocate?channel?ch01?device?type?disk;? SET?ARCHIVELOG?DESTINATION?TO?'/archivelog'; restore?ARCHIVELOG?SEQUENCE?7;? release?channel?ch01;? } ##?再次recover進(jìn)行恢復(fù)至指定時間點?2021-06-17?18:06:00? run?{? sql?'alter?session?set?nls_date_format="yyyy-mm-dd?hh24:mi:ss"';? set?until?time?'2021-06-17?18:06:00';? allocate?channel?ch01?device?type?disk;? recover?database?skip?tablespace?LTEST,EXAMPLE;? release?channel?ch01;? }?新主機(jī)實例開啟到只讀模式:
sqlplus?/?as?sysdba alter?database?open?read?only;確認(rèn)新主機(jī)實例的表數(shù)據(jù)是否正確:
sqlplus?/?as?sysdba select?*?from?lucifer.lucifer;📢 注意:?若不正確則重復(fù) 第7步 調(diào)整時間點慢慢往 2021/06/17 18:10:00 推進(jìn)恢復(fù):
##?關(guān)閉數(shù)據(jù)庫 sqlplus?/?as?sysdba shutdown?immediate;? ##?開啟數(shù)據(jù)庫到mount狀態(tài) startup?mount?pfile='/tmp/pfile.ora'; ##?重復(fù)?第7步,往前推進(jìn)1分鐘,調(diào)整時間點為?`2021/06/08?18:07:00` rman?target?/ run?{ sql?'alter?session?set?nls_date_format="yyyy-mm-dd?hh24:mi:ss"'; set?until?time?'2021-06-17?18:07:00'; allocate?channel?ch01?device?type?disk; recover?database?skip?tablespace?LTEST,EXAMPLE; release?channel?ch01; }主庫創(chuàng)建連通新主機(jī)實例的DBLINK,通過DBLINK從新主機(jī)實例撈取表數(shù)據(jù):
sqlplus?/?as?sysdba ##?創(chuàng)建dblinnk CREATE?PUBLIC?DATABASE?LINK?ORCL112 CONNECT?TO?lucifer IDENTIFIED?BY?lucifer USING?'(DESCRIPTION_LIST= (DESCRIPTION= (ADDRESS=(PROTOCOL=tcp)(HOST=10.211.55.112)(PORT=1521)) (CONNECT_DATA= (SERVICE_NAME=orcl) ) ) )'; ##?通過dblink撈取數(shù)據(jù) create?table?lucifer.lucifer_0618?as?select?/*+full(lucifer)*/?*?from?lucifer.lucifer@ORCL112; select?*?from?lucifer.lucifer_0618;至此,整個RMAN恢復(fù)過程就結(jié)束了!
寫在最后
備份永遠(yuǎn)是最后一道防線,所以備份一定要做好!!!
總結(jié)
以上是生活随笔為你收集整理的不小心删表删库了,还能救的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试官问:什么是布隆过滤器?
- 下一篇: #用construct2做游戏