Flashback Query
對于DBA們來說,這不是一件很熟悉的事嗎?John的選擇是什么呢?
在Oracle數據庫10g之前,John可能會做一個時間點恢復,來將數據庫恢復至所希望的某一時刻的狀態。不幸的是,銀行的定期日常備份大約就是在那個時間開始,這就意味著他將不得不用接近24小時的有價值的歸案日志來恢復數據庫。
Oracle9i數據庫中提供的另一種選擇是使用回閃查詢特性來重建到晚上11:00為止的該表的各行,并手動生成一組不同的表。這一方法盡管理論上可行,但如果表的數量很大,則會變得不切合實際。
幸運的是,John現在的數據庫是Oracle數據庫10g,所以他擁有更多的選擇。
回閃表
讓我們來看一下上面的情況。出問題的年末批處理可能僅影響少數表。例如,它可能僅用新的賬戶結余更新了ACCOUNTS表。如果確實是這種情況,則John可以使用回閃表特性,它會將一個表恢復到一個過去的時間點的狀態。
執行回閃表操作不需要特殊的設置。唯一的要求是表必須具有可移動的行--或者是在創建表時設置,或者是在以后利用 ALTER TABLE ACCOUNTS ENABLE ROW MOVEMENT語句設置。FLASHBACK TABLE語句從撤消段中(undo segment)讀取該表的過去映像,并利用Oracle9i中引入的回閃查詢重建表行。
如果模式所有者之外的非DBA用戶執行回閃表操作,她需要擁有對該表的SELECT、 DELETE、INSERT、ALTER和FLASHBACK權限,或者擁有等價的ANY TABLE系統權限。
對于John來說,ACCOUNTS像以下的樣子:
ACCOUNT_NO NUMBER(12),
BALANCE NUMBER(15,2)
STATUS CHAR(1)
STATUS的列值通常為A(active,活動),但是當利息計算應用程序啟動時,所有的賬戶均被凍結,此狀態也被更新為F(frozen,凍結)。當對每一賬戶都計算了利息后,該狀態被更新為I(interest applied,利息已計算)。
下面是John用使用回閃表特性的步驟:
他索要一個大概的時間點,在這一點上數據庫必須被重新檢查,答案是大約晚上11:00。
他定義一個期望返回到的邏輯參考點。下面是他現在查詢該表時所看到的內容:
select status, count(*)
from ACCOUNTS
group by status;
STATUS COUNT(*)
------ --------
I 27088
F 19999
該輸出顯示到目前為止已經有27 088個賬戶被處理(狀態=I)。 此前的狀態為A,這不是John所希望返回的位置。所希望的邏輯參考點應該是所有賬戶的狀態都為F的時間點。他必須恢復到所有賬戶狀態都為F的狀態,這大約發生于晚上11:00。
他檢查一個狀態=I的當前示例賬戶,以便為未來的校驗測試設定一個基線:
select account_no, balance
from ACCOUNTS
where status = I
and rownum < 2;
ACCOUNT_NO BALANCE
----------- --------
21633 3913.49
他發出這一語句將ACCOUNTS表恢復至那個時間:
flashback table ACCOUNTS to timestamp
to_timestamp (12/31/2003 23:00:00,mm/dd/yyyy hh24:mi:ss);
瞧! 整個表被恢復到那個時間的狀態了。只要撤消段中所保存的撤消數據允許,John便可以回閃到過去的某個時間點。John也可以不用時間標記(stamp),而是使用系統改變數目(system change number,SCN),如下所示:
flashback table ACCOUNTS
to SCN 9988653338;
此表已被恢復至晚上11:00的狀態,但這是不是所希望的時間點狀態呢?John再次檢查狀態:
select status, count(*)
from ACCOUNTS
group by status;
STATUS COUNT(*)
------ --------
I 88
F 46999
仍然有88個記錄的狀態為T。所以,晚上11:00還不夠早,John不得不返回到更早的一個時間點。他將該表回閃到更早的一個時間點上--晚上10:30--然后再次檢查狀態:
flashback table ACCOUNTS to timestamp
to_timestamp (12/31/2003 22:30:00,mm/dd/yyyy hh24:mi:ss);
select status, count(*)
from ACCOUNTS
group by status;
STATUS COUNT(*)
------ --------
A 47087
John返回到的過去時間太遠了些,所有賬戶的狀態都為A,這是F狀態之前的一個狀態。于是,他不得不向后滾動一段時間,滾動到晚上10:45。
flashback table ACCOUNTS to timestamp
to_timestamp (12/31/2003 22:45:00,mm/dd/yyyy hh24:mi:ss);
select status, count(*)
from ACCOUNTS
group by status;
STATUS COUNT(*)
------ --------
F 47087
這正是他希望的時間點。他通過選擇他以前查詢過的賬戶來確證這一點。
select balance
from ACCOUNTS
where account_no = 21633;
BALANCE
-------
3836.75
有效的結余為$3,913.49;返回到了晚上10:45的狀態。至此操作完成。可以向前和向后應用任意次回閃操作,直到到達所期望的準確時間點的狀態為止。
由于此表永遠不會被刪除,所以所有的從屬對象--如索引、約束條件、觸發器等等--都會保持完好無損。引用此表的所有獨立對象,如過程等,也都保持有效。即使是對分割表的全局索引也會保留,并保持有效。
除了ACCOUNTS表之外,如果John還希望將TXN表回閃,那么他可以應用許多由逗號隔開的表名,如下所示:
flashback table BANK.ACCOUNTS, bank.txn to scn 1234567;
通過一個功能強大的SQL語句完成了整個回閃表操作。
讓我們來研究另一種情況。假設Laura意外地刪除了一個關鍵字查詢表--GL_MASTER。意識到這一錯誤后,她問John能否恢復這個表。在 Oracle數據庫的以前一些版本中,這需要進行時間點恢復。但在Oracle數據庫10g中,刪除一個表只是將該表重命名后放置到稱作回收站的邏輯容器中。
為了恢復此表,John只發出了以下命令:
flashback table gl_master to before drop;
這個表馬上就重新出現了,不需要任何恢復操作。請注意,與前面所描述的回閃操作不同,它不需要通過撤消段重建數據;而只是從回收站中將此表取回。
回閃數據庫
如果說邏輯上的破壞不限于為數不多的幾個表,那么利用Oracle 10g中的Flashback Database(回閃數據庫)特性執行數據庫時間點恢復可以使恢復更快一些。Flashback Database不需要利用撤消空間(undo space),而是利用硬盤上被稱作快閃恢復區(flash recovery area)的另一區,它與撤消操作無關。Flashback Database允許進行數據庫時間點恢復,而不要求你首先恢復你數據庫的一個備份。
要回閃整個數據庫,John必須進行以下操作為數據庫做準備,從而使其具有回閃能力:
通過設置以下兩個參數來配置一個大小為2GB的回閃區域:
db_recovery_file_dest = /usr/users/oracle/10.1/recovery_area
db_recovery_file_dest_size = 2G
使用以下參數,以分鐘為單位配置最大回閃時間:
db_flashback_retention_target = 1440
這一數值反映出可以返回的最大時間;實際可能的時間由快閃恢復區域的可用空間大小來決定。所以這三個參數都是動態的,并可以使用ALTER SYSTEM命令進行設置。
使數據庫能夠回閃。為此,它必須處于archivelog模式下。在MOUNT階段,在OPEN之前,John發出如下命令:
alter database flashback on;
在啟動Flashback Database之后,它定期將已發生變化的塊寫入一個特殊類型的稱作回閃日志的日志文件中。這些日志不是由傳統的Log Writer (LGWR) 過程寫入,而是由一種稱作Recovery Writer (RVWR)的新過程寫入。與常規的重做日志(redo logs)不同,回閃日志既不需要由DBA創建,也不需要由他們維護;它們由Oracle Managed Files(OMF)自動在快閃恢復區域所指定的目錄中創建。這些文件不會歸檔,所以,如果在該目錄發生介質故障后就不可能再進行恢復。
回閃操作
在所描述的Acme銀行的事例中,John認為在他所處的情況下回閃表不太可行。他不得不將整個數據庫回滾到過去的某個時間點。他再一次選擇晚上11:00作為開始點,并發出以下命令:
flashback database to timestamp
to_timestamp (12/31/2003
23:00:00,mm/dd/yyyy hh24:mi:ss);
TIMESTAMP的查詢方式
SELECT * FROM table_name AS OF TIMESTAMP sysdate-2/1440? --查詢2分鐘之前的數據
SELECT * FROM table_name AS OF TIMESTAMP to_timestamp('2011-11-18 12:00:00','yyyy-mm-dd hh24:mi:ss');
當通過TIMESTAMP 來查詢歷史數據時,數據庫會吧TIMESTAMP轉換成SCN。
--查看SCN 和TIMESTAMP 的對應關系
?????? select scn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss')
?????? from sys.smon_scn_time
?????? order by scn;
回閃版本查詢
SELECT versions_startscn, versions_starttime,
versions_endscn, versions_endtime,
versions_xid, versions_operation
FROM test
VERSIONS BETWEEN TIMESTAMP systimestamp -10/1440 and systimestamp;
SELECT versions_startscn, versions_starttime,
versions_endscn, versions_endtime,
versions_xid, versions_operation
FROM test
VERSIONS BETWEEN TIMESTAMP
TO_TIMESTAMP('2011-11-18 9:00:00','yyyy-mm-dd hh24:mi:ss')
AND TO_TIMESTAMP('2011-11-18 15:38:30', 'YYYY-MM-DD HH24:MI:SS');
SELECT ID,VL,VERSIONS_STARTSCN,VERSIONS_ENDSCN, ?
VERSIONS_OPERATION, VERSIONS_XID ?
FROM test VERSIONS BETWEEN SCN 1273892 AND 1273922; ?
select * from test versions between timestamp systimestamp -10/1440 and systimestamp;
DDL查詢
-----------------------------------------------------------------
SELECT ? OBJECT_NAME, --對象名?
OBJECT_TYPE, --對象類型?
TO_CHAR(CREATED, ? 'YYYY-Mon-DD ? HH24:MI ') ? CREATE_TIME, --創建時間?
TO_CHAR(LAST_DDL_TIME, ? 'YYYY-Mon-DD ? HH24:MI ') ? MOD_TIME, ? --修改時間?
TIMESTAMP, --時間戳?
STATUS --狀態?
FROM ? USER_OBJECTS?
? WHERE ? to_char(LAST_DDL_TIME, 'yyyymmdd ')> '&日期變量 ';
總結
以上是生活随笔為你收集整理的Flashback Query的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: goldengate 故障及解决方法汇总
- 下一篇: Oracle数据块原理深入剖析