閃回資料庫的應用場景和測試

2023-06-28 06:00:42

如果是使用者主生產環境,通常不會有使用者會開啟這個功能。
但如果是在ADG備庫端,就會有不少客戶選擇開啟這個功能,這可以有效補充誤操作應急處置方法。

今天給某客戶做技術支援的時候,在現場遇到一個蠻有意思的問題:
XTTS測試場景,庫非常大,資料檔案很多,遠超db_files的預設值。
在表空間後設資料匯入階段,因此中斷報錯退出,修改db_files引數後發現很多表空間資料檔案已經存在,壓力就比較大,還好找到了方法drop tablespace xxx including contents的方式,注意還不能是OMF管理的,否則即便不加including datafiles也會被刪掉,那就麻煩了。。

如果能參考我之前寫過的一篇《XTTS系列之一:U2L遷移解決方案之XTTS的使用》,會發現我通常會建議大家在這種關鍵測試節點前,都會做一個動作;

就是開啟閃回資料庫的基礎上,建立強制還原點,這樣有任何問題,直接閃回資料庫到操作前狀態即可。

這個動作非常簡單,同時也為了順便驗證下在備庫開啟的步驟,我就在自己一套19c的ADG備庫環境下驗證下這個開啟操作:

1.確認db_recovery_file_dest_size 和 db_recovery_file_dest 的設定值

我這裡單範例設定到檔案系統了,你也可以設定到ASM磁碟組中:

SQL> alter system set db_recovery_file_dest_size=100g scope=both;
System altered.

SQL> alter system set db_recovery_file_dest='/flash/fast_recovery_area' scope=both;
System altered.

2.開啟閃回並確認狀態

備庫在應用的話,直接開啟會報錯ORA-01153,需要取消應用再開啟閃回,開啟閃回後再啟動備庫紀錄檔應用:

--1.直接開啟會報錯ORA-01153:
SQL> select database_role, open_mode from v$database;

DATABASE_ROLE	 OPEN_MODE
---------------- --------------------
PHYSICAL STANDBY READ ONLY WITH APPLY

SQL> alter database flashback on;
alter database flashback on
*
ERROR at line 1:
ORA-01153: an incompatible media recovery is active

--2.需要取消應用再開啟:
SQL> recover managed standby database cancel;
Media recovery complete.
SQL> select database_role, open_mode from v$database;

DATABASE_ROLE	 OPEN_MODE
---------------- --------------------
PHYSICAL STANDBY READ ONLY

SQL> alter database flashback on;

Database altered.

SQL> select flashback_on from v$database;

FLASHBACK_ON
------------------
YES

--3.開啟閃回後再啟動備庫紀錄檔應用
SQL> recover managed standby database disconnect;
Media recovery complete.
SQL> select database_role, open_mode from v$database;

DATABASE_ROLE	 OPEN_MODE
---------------- --------------------
PHYSICAL STANDBY READ ONLY WITH APPLY

3.建立一個強制還原點

比如這裡建立 before_imp_xtts 強制還原點:

SQL> create restore point before_imp_xtts guarantee flashback database;
Restore point created.

SQL> select name from v$restore_point;
--確認有剛建立的restore point。

注意:如果是在備庫建立,那也是需要先cancel紀錄檔應用才能建立的!

4.舉例ADG備庫建立還原點

比如舉例在備庫建立一個 before_truncate_t 強制還原點:

目前T表有9條資料:

SQL> select count(*) from t;

  COUNT(*)
----------
	 9

在ADG備庫建立還原點:

SQL> recover managed standby database cancel;
Media recovery complete.
SQL> create restore point before_truncate_t guarantee flashback database;

Restore point created.

開啟應用後(19cADG實時應用不再需要指定using current logfile關鍵字),
主庫此時去truncate T這張表,ADG備庫查詢已經實時同步被刪除了。

SQL> recover managed standby database disconnect;
Media recovery complete.
SQL> select count(*) from t;

  COUNT(*)
----------
	 9

SQL> select count(*) from t;

  COUNT(*)
----------
	 0

如何閃回到before_truncate_t呢?

SQL> flashback database to restore point before_truncate_t;
flashback database to restore point before_truncate_t
*
ERROR at line 1:
ORA-01153: an incompatible media recovery is active


SQL> recover managed standby database cancel;
Media recovery complete.
SQL> flashback database to restore point before_truncate_t;

Flashback complete.

SQL> select count(*) from t;
select count(*) from t
                     *
ERROR at line 1:
ORA-01219: database or pluggable database not open: queries allowed on fixed
tables or views only


SQL> select status from v$instance;

STATUS
------------
MOUNTED

SQL> alter database open;

Database altered.

SQL> select count(*) from t;

  COUNT(*)
----------
	 9

還是要在停止應用紀錄檔的狀態下,直接閃回資料庫到指定的這個restore point,然後開庫就可以看到被誤操作的T表資料又回來了~

可能有人會問,除了計劃內的測試,誰也不會在誤操作之前去手工建立還原點,真實誤操作場景如何進行閃回呢?
蠻好的問題,其實閃回可以基於時間進行的。
刪除還原點,然後開啟同步,又到了誤操作場景,如何操作呢?

SQL> drop restore point BEFORE_TRUNCATE_T;

Restore point dropped.

SQL> recover managed standby database disconnect;
Media recovery complete.
SQL> select count(*) from t;

  COUNT(*)
----------
	 0

可以查詢閃回資料庫的資訊:

SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

Session altered.

SQL> SELECT * FROM V$FLASHBACK_DATABASE_STAT
  2  /

BEGIN_TIME	    END_TIME		FLASHBACK_DATA	  DB_DATA  REDO_DATA ESTIMATED_FLASHBACK_SIZE	  CON_ID
------------------- ------------------- -------------- ---------- ---------- ------------------------ ----------
2023-06-27 22:09:07 2023-06-27 22:51:28       25362432	  7741440	   0			    0	       0

--此時主庫又插入一條資料,備庫也同步了:
SQL>  select count(*) from t;

  COUNT(*)
----------
	 1

SQL> select TIMESTAMP_TO_SCN(to_timestamp('2023-06-27 22:51:28','yyyy-mm-dd hh24:mi:ss')) from dual;

TIMESTAMP_TO_SCN(TO_TIMESTAMP('2023-06-2722:51:28','YYYY-MM-DDHH24:MI:SS'))
---------------------------------------------------------------------------
								   58518875
注意:這個轉換其實不夠精確,3秒內的時間都被轉換成同一個SCN。但這裡的場景是足夠用的;閃回到這個SCN,flashback database to scn 58518875;

SQL> recover managed standby database cancel;
Media recovery complete.
SQL> flashback database to scn 58518875;

Flashback complete.

SQL> alter database open;

Database altered.

SQL> select * from t;

no rows selected

SQL>

看T表又無資料了,相當於再沒有任何還原點存在的情況下,可以直接閃回到某個時間,而這個時間可以是 V$FLASHBACK_DATABASE_STAT 查到時間範圍區間內的任意時間。
真的是蠻強大的一個功能。

Tips:這裡用到了時間和SCN的轉換,其實Oracle很多場景都會用到SCN和時間的互相轉換,可以記下:

  • 將SCN轉換成時間戳,使用 SCN_TO_TIMESTAMP(scn_number)
  • 將時間戳轉換成SCN,使用 TIMESTAMP_TO_SCN(timestamp)
--eg:將SCN轉換成時間戳,使用 SCN_TO_TIMESTAMP(scn_number)
SQL> select SCN_TO_TIMESTAMP(58518875) from dual;

SCN_TO_TIMESTAMP(58518875)
---------------------------------------------------------------------------
27-JUN-23 10.51.27.000000000 PM

--eg:將時間戳轉換成SCN,使用 TIMESTAMP_TO_SCN(timestamp)
SQL> select TIMESTAMP_TO_SCN(to_timestamp('2023-06-27 22:51:28','yyyy-mm-dd hh24:mi:ss')) from dual;

TIMESTAMP_TO_SCN(TO_TIMESTAMP('2023-06-2722:51:28','YYYY-MM-DDHH24:MI:SS'))
---------------------------------------------------------------------------
								   58518875