不小心删表删库了,还能救
前言
常在河邊走,哪能不濕鞋?
今天有客戶聯系說誤更新數據表,導致數據錯亂了,希望將這張表恢復到?一周前?的指定時間點。
-
數據庫版本為?11.2.0.1
-
操作系統是?Windows64
-
數據已經被更改超過1周時間
-
數據庫已開啟歸檔模式
-
沒有DG容災
-
有RMAN備份
下面模擬一下問題的詳細解決過程!
一、分析
以下只列出常規恢復手段:
-
數據已經誤操作超過一周,所以排除使用UNDO快照來找回;
-
沒有DG容災環境,排除使用DG閃回;
-
主庫已開啟歸檔模式,并且存在RMAN備份,可使用RMAN異機恢復表對應表空間,使用DBLINK撈回數據表;
-
Oracle 12C后支持單張表恢復;
結論:安全起見,使用RMAN異機恢復表空間來撈回數據表。
二、思路
客戶希望將表數據恢復到 <2021/06/08 17:00:00> 之前某個時間點。
大致操作步驟如下:
-
主庫查詢誤更新數據表對應的表空間和無需恢復的表空間。
-
新主機安裝Oracle 11.2.0.1數據庫軟件,無需建庫,目錄結構最好保持一致。
-
主庫拷貝參數文件,密碼文件至新主機,根據新主機修改參數文件和創建新實例所需目錄。
-
新主機使用修改后的參數文件打開數據庫實例到nomount狀態。
-
主庫拷貝備份的控制文件至新主機,新主機使用RMAN恢復控制文件,并且MOUNT新實例。
-
新主機RESTORE TABLESPACE恢復至時間點 ?<2021/06/08 16:00:00>。
-
新主機RECOVER DATABASE SKIP TABLESPACE恢復至時間點 ?<2021/06/08 16:00:00>。
-
新主機實例開啟到只讀模式。
-
確認新主機實例的表數據是否正確,若不正確則重復?第7步?調整時間點慢慢往?<2021/06/08 ?17:00:00>?推進恢復。
-
主庫創建連通新主機實例的DBLINK,通過DBLINK從新主機實例撈取表數據。
📢 注意:?選擇表空間恢復是因為主庫數據量比較大,如果全庫恢復需要大量時間。
三、測試環境模擬
為了數據脫敏,因此以測試環境模擬場景進行演示!
?? 測試環境可以使用腳本安裝,可以使用博主編寫的 Oracle 一鍵安裝腳本,同時支持單機和 RAC 集群模式!
1、環境準備
測試環境信息如下:
| 主庫 | rhel6.9 | orcl | orcl | 11.2.0.1 | 10.211.55.111 |
| 新主機 | rhel6.9 | orcl | 不創建實例 | 11.2.0.1 | 10.211.55.112 |
2、模擬測試場景
主庫開啟歸檔模式:
sqlplus?/?as?sysdba ##?設置歸檔路徑 alter?system?set?log_archive_dest_1='LOCATION=/archivelog'; ##?重啟開啟歸檔模式 shutdown?immediate startup?mount alter database archivelog; ##?打開數據庫 alter?database?open;創建測試數據:
sqlplus?/?as?sysdba ##?創建表空間 create?tablespace?lucifer?datafile?'/oradata/orcl/lucifer01.dbf'?size?10M?autoextend?off; create?tablespace?ltest?datafile?'/oradata/orcl/ltest01.dbf'?size?10M?autoextend?off; ##?創建用戶 create?user?lucifer?identified?by?lucifer; grant?dba?to?lucifer; ##?創建表 conn?lucifer/lucifer create?table?lucifer(id?number?not?null,name?varchar2(20))?tablespace?lucifer; ##?插入數據 insert?into?lucifer?values(1,'lucifer'); insert?into?lucifer?values(2,'test1'); insert?into?lucifer?values(3,'test2'); commit;進行數據庫全備:
rman?target?/ ##?進入?rman?后執行以下命令 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; }模擬數據修改:
sqlplus?/?as?sysdba conn?lucifer/lucifer delete?from?lucifer?where?id=1; update?lucifer?set?name='lucifer'?where?id=2; commit;📢 注意:?為了模擬客戶環境,假設無法通過UNDO快照找回,當前刪除時間點為:<2021/06/17 18:10:00>。
如果使用UNDO快照,比較方便:
sqlplus?/?as?sysdba ##?查找UNDO快照數據是否正確 select?*?from?lucifer.lucifer?as?of?timestamp?to_timestamp('2021-06-17?18:05:00','YYYY-MM-DD?HH24:MI:SS'); ##?將UNDO快照數據撈至新建表中 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完整恢復過程
主庫查詢誤更新數據表對應的表空間和無需恢復的表空間:
sqlplus?/?as?sysdba ##?查詢誤更新數據表對應表空間 select?owner,tablespace_name?from?dba_segments?where?segment_name='LUCIFER'; ##?查詢所有表空間 select?tablespace_name?from?dba_tablespaces;主庫拷貝參數文件,密碼文件至新主機,根據新主機修改參數文件和創建新實例所需目錄:
##?生成pfile參數文件 sqlplus?/?as?sysdba create?pfile='/home/oracle/pfile.ora'?from?spfile; exit; ##?拷貝至新主機 su?-?oracle scp?/home/oracle/pfile.ora?10.211.55.112:/tmp scp?$ORACLE_HOME/dbs/orapworcl?10.211.55.112:$ORACLE_HOME/dbs ##?新主機根據實際情況修改參數文件并且創建目錄 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新主機使用修改后的參數文件打開數據庫實例到nomount狀態:
sqlplus?/?as?sysdba startup?nomount?pfile='/tmp/pfile.ora';主庫拷貝備份的控制文件至新主機,新主機使用RMAN恢復控制文件,并且MOUNT新實例:
rman?target?/ list?backup?of?controlfile; exit; ##?拷貝備份文件至新主機 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 ##?新主機恢復控制文件并開啟到mount狀態 rman?target?/ restore?controlfile?from?'/tmp/backlv0_ORCL_20210617_1075485924_9_1'; alter?database?mount;通過?list backup of controlfile;?可以看到控制文件位置:
新主機RESTORE TABLESPACE恢復至時間點?<2021/06/17 18:06:00>?:
##?新主機注冊備份集 rman?target?/ catalog?start?with?'/tmp/backlv0_ORCL_20210617_107548592'; crosscheck?backup; delete?noprompt?expired?backup; delete?noprompt?obsolete?device?type?disk; ##?恢復表空間LUCIFER和系統表空間,指定時間點?`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; }新主機RECOVER DATABASE SKIP TABLESPACE恢復至時間點?<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:?客戶環境是Windows,執行這一步最后報錯,手動offline數據文件依然無法開啟數據庫。
解決方案:
sqlplus?/?as?sysdba ##?將恢復跳過的表空間都offline?drop掉,執行以下查詢結果 select?'alter?database?datafile?'||?file_id?||'?offline?drop;'?from?dba_data_files?where?tablespace_name?in?('LTEST','EXAMPLE'); ##?再次開啟數據庫 alter?database?open?read?only;📢 注意:?如果顯示缺歸檔日志,可以參考如下步驟:
sqlplus?/?as?sysdba ##?查詢恢復需要的歸檔日志號時間? 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進行恢復至指定時間點?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;? }?新主機實例開啟到只讀模式:
sqlplus?/?as?sysdba alter?database?open?read?only;確認新主機實例的表數據是否正確:
sqlplus?/?as?sysdba select?*?from?lucifer.lucifer;📢 注意:?若不正確則重復 第7步 調整時間點慢慢往 2021/06/17 18:10:00 推進恢復:
##?關閉數據庫 sqlplus?/?as?sysdba shutdown?immediate;? ##?開啟數據庫到mount狀態 startup?mount?pfile='/tmp/pfile.ora'; ##?重復?第7步,往前推進1分鐘,調整時間點為?`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; }主庫創建連通新主機實例的DBLINK,通過DBLINK從新主機實例撈取表數據:
sqlplus?/?as?sysdba ##?創建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撈取數據 create?table?lucifer.lucifer_0618?as?select?/*+full(lucifer)*/?*?from?lucifer.lucifer@ORCL112; select?*?from?lucifer.lucifer_0618;至此,整個RMAN恢復過程就結束了!
寫在最后
備份永遠是最后一道防線,所以備份一定要做好!!!
總結
以上是生活随笔為你收集整理的不小心删表删库了,还能救的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试官问:什么是布隆过滤器?
- 下一篇: #用construct2做游戏