oracle異機恢復測試


(一)問題背景

最近在生產環境中,開發人員誤操作,使用truncate將oracle數據庫某個表的數據全部刪除了,在刪除之后,開發人員發現自己闖禍了,於是聯系值班的DBA進行緊急數據恢復。

經過分析,表被truncate后,使用一般的閃回表、閃回查詢、閃回事物等方法,是不可能將數據找回來的,可以使用閃回數據庫、閃回數據歸檔的方法來進行恢復,但是通常在生產環境中,都不會開啟這2個特性,所以剩下的只有使用RMAN進行數據恢復了。

對於使用RMAN進行數據恢復,可以在生產環境上直接進行,也可以恢復到其它機器上。

  • 直接在生產環境上恢復:①需要停止生產數據庫;②數據庫需要保持一致性,比如說,我需要將數據庫恢復到12:00,那么數據庫中其他表的數據也將恢復到12點,有可能會丟失較多數據;③如果恢復過程中出現其它問題也比較麻煩,耽誤了生產業務執行。
  • 恢復到其它機器上:②不需要停生產庫;②僅僅丟失truncate表的數據,比如說,我需要將數據庫恢復到12:00,那么我只需將整個庫在測試環境上恢復到12點,再將我們丟失表的數據通過DB_LINK或數據泵等方式恢復到生產環境,生產環境其它表的數據是不受影響的;③恢復失敗,並不會影響到生產庫。

所以,經過一番考慮,決定將數據庫恢復到其它機器上,然后再將truncate表的數據導回到生產環境。

此次恢復操作是同事做的,在恢復過程中,由於流程不熟悉,查資料耽誤了一些時間(大約20分鍾),雖然數據庫恢復完成了,但沒有達到快速恢復的要求。思考了一下,假如自己來做,能否在開發人員焦急等待的情況下,自己毫不慌亂、快速穩定的完成數據庫恢復?確實是不可能的。一方面恢復流程不熟練,畢竟數據庫恢復操作一年也不可能遇到幾次,另一方面在用戶及開發人員催促的情況下,DBA也很容易慌張,影響效率。因此最好的方式是:提前演練、寫好操作流程。當故障發生時,照着文檔操作,以最快的速度恢復生產。

 

(二)環境准備

  生產環境 異機環境
操作系統 RedHat6.7 RedHat6.7
數據庫版本 11.2.0.4(RAC,2個節點) 11.2.0.4(單節點)
db_name prodb prodb
instance_name prodb1、prodb2 prodb
數據庫安裝情況 安裝GI+數據庫軟件+創建數據庫 安裝GI+數據庫軟件 (不用創建數據庫)
磁盤組信息 OCR   : 3*1GB,normal
DATA :3*5GB,external
ARCH :  1*5GB,external
OCR   : 3*1GB,normal
DATA :3*5GB,external
ARCH :  1*5GB,external

備注:為了方便,在后續環境中,生產環境數據庫簡稱“生產庫”,異機環境的數據庫簡稱“測試庫”。

 

(三)測試方案

image

 

(四)詳細執行過程

(4.1)創建測試表

這里創建了2個測試表,作用分別如下:

lijiaman.test01:用於做truncate測試的表,最后在測試庫需要進行test01表的恢復。

lijiaman.test02:用於模擬數據庫事務,對該表不斷執行插入操作,使得數據庫產生大量歸檔日志。

(Ⅰ)表test01,一共有14筆數據。

SQL> CREATE TABLE test01 AS SELECT * FROM scott.emp;
Table created

SQL> select count(*) from test01;
  COUNT(*)
----------
        14

(ⅠⅠ)表test02,持續往里面寫入數據

--創建表test02
create table test02
(
    col1      number,    
    col2      number,
    col3      varchar2(30),
    col4      date,
    col5      varchar2(100)                           
);

--創建隨機數據插入存儲過程
create or replace procedure p_insert_test02 is
BEGIN
  FOR i IN 1..10000 LOOP
  insert into test02(col1,col2,col3,col4,col5)
  values
    ((select round(dbms_random.value(1, 100000000)) from dual),
     (select round(dbms_random.value(10000, 100000000)) from dual),
     (select dbms_random.string('a', 25) from dual),
     sysdate,
     (select dbms_random.string('a', 85) from dual));
  commit;
  END LOOP;
end  p_insert_test02;

--制定job,沒隔30s執行一次上面的存儲過程
declare
job1 number;
begin
sys.dbms_job.submit(job => job1,
what => 'p_insert_test02;',
next_date => sysdate,
interval => 'sysdate + 30/(1440*60)');                --每隔30s向test02表插入10000筆隨機數據
commit;
end;
/

 

(4.2)對數據庫進行完全備份

rman target /

RMAN> run {
allocate channel c1 type disk;
allocate channel c2 type disk;
sql' alter system archive log current';
backup database format '/databaseBackup/full_db_%U';
sql' alter system archive log current';
backup archivelog all format '/databaseBackup/archlog_%U';
backup current controlfile format '/databaseBackup/controlfile_%U';
backup spfile format '/databaseBackup/spfile_%U';
release channel c1;
release channel c2;
}

生成的備份集如下:

[oracle@node1 databaseBackup]$ ls -l
total 4136752
-rw-r----- 1 oracle asmadmin 1451128832  Sep 27 19:27 archlog_0iucr7hg_1_1
-rw-r----- 1 oracle asmadmin 1462116352  Sep 27 19:27 archlog_0jucr7hh_1_1
-rw-r----- 1 oracle asmadmin     1406464   Sep 27 19:27 archlog_0kucr7lr_1_1
-rw-r----- 1 oracle asmadmin   18841600   Sep 27 19:28 controlfile_0lucr7m2_1_1
-rw-r----- 1 oracle asmadmin  805953536   Sep 27 19:25 full_db_0eucr7f7_1_1
-rw-r----- 1 oracle asmadmin  477528064   Sep 27 19:25 full_db_0fucr7f7_1_1
-rw-r----- 1 oracle asmadmin   18841600   Sep 27 19:25 full_db_0gucr7h3_1_1
-rw-r----- 1 oracle asmadmin        98304   Sep 27 19:25 full_db_0hucr7ha_1_1
-rw-r----- 1 oracle asmadmin        98304   Sep 27 19:28 spfile_0mucr7m5_1_1

確認歸檔日志備份情況,可以看到,本次全備份歸檔日志備份到了thread1:57,thread2:48。

RMAN> list archivelog all;

List of Archived Log Copies for database with db_unique_name PRODB
=====================================================================

Key     Thrd  Seq     S  Low Time
------- ---- ------- - ---------
3            1    6       A 24-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_24/thread_1_seq_6.258.1019832847
......
100        1     57      A 27-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_27/thread_1_seq_57.355.1020108489

1           2     1       A 24-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_24/thread_2_seq_1.256.1019830885
......
80         2     48      A 24-SEP-19
        Name: +ARCH/prodb/archivelog/2019_09_24/thread_2_seq_48.335.1019838555

 

(4.3)數據庫正常運行,產生大量歸檔

由於日志序列號是遞增的(以resetlogs打開數據庫例外),因此查詢每個實例上生成的最大日志即可

SELECT *
FROM 
(SELECT thread#,
       SEQUENCE#,
       NAME,
       ROW_NUMBER() OVER(PARTITION BY thread# ORDER BY SEQUENCE# DESC) rn
  FROM V$ARCHIVED_LOG)
WHERE rn=1;

結果為:

image

即thread1上的歸檔日志最大序列號為67,thread2上的歸檔日志最大序列號為48(這里因為個人電腦開較多虛擬機太卡,所以只開了節點1,節點2就沒有日志生成,並不影響本次實驗結果的准確性)。

 

(4.4)模擬test01表被truncate,記下時間

SQL> select sysdate from dual;

SYSDATE
-------------------
2019-09-27 19:37:31

SQL> 
SQL> truncate table test01;

Table truncated.

 

(4.5)數據庫正常運行,產生大量歸檔

上一次備份到了sequence=57的日志,上一次備份后又生成了25個日志,這里生成大量日志是為了模擬生產數據庫這次交易的情況。

image

 

(4.6)開發人員發現表數據被truncate

開發人員發現程序報錯,查看表test01,發現數據全沒了,開發人員確認數據被自己刪除(假設)。

 

(4.7)DBA執行異機恢復

思路整理:

image

本次恢復,需要將test01表恢復到truncate之前,我們需要有執行truncate操作之前的數據庫全備和歸檔備份。第一次全備歸檔日志文件之備份到了thread1=57,thread2=48,在執行全被之后,又生成了許多的日志文件,我們要將數據庫恢復到truncate之前(這里以我們記錄的時間2019-09-27 19:37:31 為恢復點),那么我們還需要新的日志來做恢復,需要的日志如下:

thread1:日志57~67肯定需要,日志67~82不一定需要;

thread2:由於節點未開啟,不需要日志來做恢復。

 

step1:將生產庫的備份集傳到測試庫

[oracle@node1 databaseBackup]$ scp * 192.168.10.66:/databaseBackup/

step2:對恢復需要的歸檔日志進行再次備份,得到缺少的歸檔日志

run {
allocate channel c1 type disk;
sql' alter system archive log current';
backup archivelog all format '/databaseBackup/archlog_20190927_%U';
release channel c1;
}

得到的歸檔日志備份集如下:

-rw-r----- 1 oracle asmadmin 1621476864 Sep 27 20:50 archlog_20190927_0nucrcd2_1_1
-rw-r----- 1 oracle asmadmin 1643560960 Sep 27 20:51 archlog_20190927_0oucrcg5_1_1
-rw-r----- 1 oracle asmadmin 1581030912 Sep 27 20:53 archlog_20190927_0pucrcjj_1_1

傳送到備庫上
[oracle@node1 databaseBackup]$ scp archlog_20190927_0* 192.168.10.66:/databaseBackup/
step3:根據生產庫的pfile,構造一個測試庫的pfile

[oracle@test dbs]$ pwd
/u01/app/oracle/product/11.2.0/db_1/dbs

[oracle@test dbs]$ vim init initprodb.ora
# 添加如下信息
audit_file_dest='/u01/app/oracle/admin/prodb/adump'
audit_trail='db'
compatible='11.2.0.4.0'
control_files='+DATA/prodb/controlfile/current.260.1019830577'
db_block_size=8192
db_create_file_dest='+DATA'
db_domain=''
db_name='prodb'
diagnostic_dest='/u01/app/oracle'
dispatchers='(PROTOCOL=TCP) (SERVICE=prodbXDB)'
enable_ddl_logging=TRUE
log_archive_dest_1='LOCATION=+arch'
log_archive_format='%t_%s_%r.dbf'
open_cursors=300
pga_aggregate_target=399507456
processes=200
remote_login_passwordfile='exclusive'
sessions=225
sga_target=1199570944
prodb.undo_tablespace='UNDOTBS1'

[oracle@test dbs]$ ls
hc_prodb.dat  hc_testdb1.dat  hc_testdb.dat  init.ora  initprodb.ora  lkTESTDB

創建pfile里面涉及到的路徑:

[oracle@test ~]$ mkdir -p /u01/app/oracle/admin/prodb/adump

step4:將備庫啟動到nomount狀態

[oracle@test ~]$ export ORACLE_SID=prodb
[oracle@test ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Fri Sep 27 20:58:15 2019

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup nomount;
ORACLE instance started.

Total System Global Area 1202556928 bytes
Fixed Size            2252704 bytes
Variable Size          402653280 bytes
Database Buffers      788529152 bytes
Redo Buffers            9121792 bytes
SQL>

step5:將數據庫添加到HA中,以便可以使用ASM存儲

[oracle@test ~]$ srvctl add database -d prodb -o /u01/app/oracle/product/11.2.0/db_1

step6:恢復控制文件,修改pfile文件,重新啟動數據庫到mount狀態

RMAN> restore controlfile from "/databaseBackup/controlfile_0lucr7m2_1_1";

注意:此時存在一個問題,我們在構造pfile文件的時候,里面填寫了控制文件的位置,這個位置是生產庫上的位置,我們執行控制文件恢復后,需要對參數文件中的control_files參數進行修改,修改方法如下:

--首先,確認contril file在asm中的位置,

ASMCMD> pwd
+data/prodb/controlfile
ASMCMD> ls -lt
Type         Redund  Striped  Time             Sys  Name
CONTROLFILE  UNPROT  FINE     SEP 27 21:00:00  Y    current.256.1020114329

--接下來,修改pfile文件的control_files參數

[oracle@test ~]$ cd $ORACLE_HOME/dbs
[oracle@test dbs]$ vim initprodb.ora 
# 改control_files位置
control_files='+data/prodb/controlfile/current.256.1020114329'

--重啟數據庫到mount狀態

[oracle@test ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Fri Sep 27 21:17:26 2019

Copyright (c) 1982, 2013, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options

SQL> shutdown immediate
ORA-01507: database not mounted


ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.

Total System Global Area 1202556928 bytes
Fixed Size            2252704 bytes
Variable Size          402653280 bytes
Database Buffers      788529152 bytes
Redo Buffers            9121792 bytes
Database mounted.
SQL>

step7:注冊新的歸檔日志備份集到備庫的控制文件中

RMAN> catalog backuppiece "/databaseBackup/archlog_20190927_0nucrcd2_1_1";
RMAN> catalog backuppiece "/databaseBackup/archlog_20190927_0oucrcg5_1_1";
RMAN> catalog backuppiece "/databaseBackup/archlog_20190927_0pucrcjj_1_1";

step8:恢復數據庫到truncate之前

RMAN>SQL"ALTER SESSION SET NLS_LANGUAGE=''AMERICAN''";
RMAN>SQL"ALTER SESSION SET NLS_DATE_FORMAT=''YYYY-MM-DD HH24:MI:SS''";
RUN{
SET UNTIL TIME '2019-09-27 19:37:31';
RESTORE DATABASE;
RECOVER DATABASE;
}
step9:確認數據是已經否恢復回來
--先以只讀方式打開數據庫,如果有問題,還可以重新執行恢復
SQL> alter database open read only;
Database altered.

--確認數據是否找回來
SQL> select count(*) from lijiaman.test01;
  COUNT(*)
----------
    14

step10:如果沒問題,關閉數據庫,以resetlogs方式打開

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.

Total System Global Area 1202556928 bytes
Fixed Size            2252704 bytes
Variable Size          402653280 bytes
Database Buffers      788529152 bytes
Redo Buffers            9121792 bytes
Database mounted.

SQL> alter database open resetlogs;

Database altered.

恢復完成。

(4.8)將恢復的數據導入到生產環境

可以使用expdp/impdp或者是dblink將數據從測試庫導入到生產庫中。

【完】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM