大家好,這里是公眾號 DBA學習之路,分享一些學習數據庫路上的知識和經驗。

目錄
前言
常在河邊走,哪能不濕鞋?
今天有客戶聯系說誤更新數據表,導致數據錯亂了,希望將這張表恢復到 一周前 的指定時間點。
- 數據庫版本為
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 集群模式!
更多更詳細的腳本使用方式可以訂閱專欄:Oracle 一鍵安裝腳本實操合集,持續更新中!!!。
1、環境準備
測試環境信息如下:
| 節點 | 主機版本 | 主機名 | 實例名 | Oracle版本 | IP地址 |
|---|---|---|---|---|---|
| 主庫 | 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恢復過程就結束了!
寫在最后
備份永遠是最后一道防線,所以備份一定要做好!!!
往期精彩文章
Oracle 一鍵巡檢自動生成 Word 報告
Oracle 一鍵安裝合集
Oracle一鍵安裝腳本的 21 個疑問與解答
Oracle一鍵巡檢腳本的 21 個疑問與解答
全網首發:Oracle 23ai 一鍵安裝腳本(非 RPM)
Oracle 19C 最新 RU 補丁 19.24 ,一鍵安裝!
Oracle Linux 7.9 一鍵安裝 Oracle 19C
RedHat 9.4(aarch64) 一鍵安裝 Oracle 19C
openEuler 22.03 LTS SP4 一鍵安裝 Oracle 19C RAC
RHEL 7.9 一鍵安裝 Oracle 19C 19.23 RAC
Oracle DataGuard GAP 修復手冊
優化 Oracle:最佳實踐與開發規范
DBA 必備:Linux 軟件源配置全攻略
Linux 一鍵配置時鐘同步全攻略





