事務(wù)管理 學(xué)習(xí)如何通過收回具體的事務(wù)及其依賴項來識別并回滾時間。 Oracle 企業(yè)管理器中的 LogMiner 界面 LogMiner 是 Oracle 數(shù)據(jù)庫中一個經(jīng)常受到忽視但功能卻非常強(qiáng)大的工具。它可用于從重做日志文件中提取 DML 語句 — 引發(fā)事務(wù)的初始 SQL 以及甚至能取消事務(wù)的 SQL。(有關(guān) LogMiner 的介紹及其工作方式,請參閱我在 Oracle 雜志上發(fā)表的文章“挖掘線索”。)至今為止,這一功能強(qiáng)大的工具由于缺少較簡單的界面而得不到普遍認(rèn)可。然而,在 Oracle 數(shù)據(jù)庫 11g 中, Oracle 企業(yè)管理器具有一個使用 LogMiner 從重做日志提取事務(wù)的圖形界面,這為使用這一工具檢查和回滾事務(wù)帶來了極大的便利。(注:與以前的版本相同,如果愿意,您可以繼續(xù)使用 DBMS_LOGMNR 程序包執(zhí)行命令行驅(qū)動的日志挖掘。) 下面我們來看一個示例。要啟用日志挖掘,您只需針對數(shù)據(jù)庫或至少是針對表啟用的小型追加日志。閃回事務(wù)需要主鍵日志。要針對整個數(shù)據(jù)庫啟用它,請執(zhí)行以下命令: SQL> alter database add supplemental log data; Database altered. SQL> alter database add supplemental log data (primary key) columns; Database altered. 現(xiàn)在,請看以下由某個應(yīng)用程序針對數(shù)據(jù)庫執(zhí)行的語句: SQL> insert into res values (100002,sysdate,12,1); 1 row created. SQL> commit; Commit complete. SQL> update res set hotel_id = 13 where res_id = 100002; 1 row updated. SQL> commit; Commit complete. SQL> delete res where res_id = 100002; 1 row deleted. SQL> commit; Commit complete. 仔細(xì)觀察這些語句:每個語句后都有一個提交語句,這表明每個語句都是一個事務(wù)。現(xiàn)在讓我們看一下如何使用 Oracle 數(shù)據(jù)庫 11g 數(shù)據(jù)庫控制中的 LogMiner 檢查事務(wù)。 在企業(yè)管理器屏幕中,從數(shù)據(jù)庫主頁進(jìn)入 Availability 選項卡。 單擊 Manage 下的 View and Manage Transactions。LogMiner 主界面顯示,如下圖所示: 您可以輸入具體的時間范圍或 SCN 范圍來搜索事務(wù)。在上圖中,我已經(jīng)在 Query Time Range 中輸入了一個時間范圍進(jìn)行搜索。在 Query Filter 中,我只用了 SCOTT 的事務(wù),因為其曾用來執(zhí)行過所有的 DML。在 Advanced Query 部分中,您可以輸入其他任何過濾器。填完所有的域后,單擊 Continue。 這將激活日志挖掘進(jìn)程對重做日志(在線的和存檔的,必要的話)進(jìn)行搜索,尋找用戶 SCOTT 發(fā)布的事務(wù)。進(jìn)程結(jié)束后,您將看到結(jié)果屏幕。 結(jié)果屏幕的頂端部分與下圖類似: 結(jié)果表明,通過搜索找到兩個由 SCOTT 發(fā)布的事務(wù),這些事務(wù)影響了兩條記錄。 屏幕的底端部分顯示了這些事務(wù)的詳細(xì)信息。這是屏幕的局部視圖。您可以看到,事務(wù)顯示為 1 ins (表示“1 條插入語句”)。最左邊一欄顯示了事務(wù)標(biāo)識符 (XID),是唯一標(biāo)識事務(wù)的編號。 如果點(diǎn)擊事務(wù)標(biāo)識符,您可以看到相應(yīng)事務(wù)的詳細(xì)信息,如下圖所示: 如您所見,您可以使用數(shù)據(jù)庫控制搜索和識別事務(wù)。單擊按鈕 Previous Transaction 和 Next Transaction 可以滾動瀏覽通過搜索找到的所有事務(wù)。 使用案例 如何使用這一特性?有幾種方法。最重要的用途可能就是查清“誰”做了“什么”。如果由于性能原因您沒有啟用審計,或者僅僅是沒有保留審計記錄,您只需通過挖掘重做日志(在線的和存檔的)在 LogMiner 界面中搜索相關(guān)線索即可。在搜索屏幕中,您可以在 Query Filter 下的 Advanced Query 域中輸入附加過濾條件。 假設(shè),您要查找一個插入、刪除或更新了 RES_ID = 100002 的記錄的事務(wù)。您可以使用 dbms_logmnr 程序包中的 column_present 函數(shù)在重做流中搜索具體的值,如下所示: 這個函數(shù)將會提取 SCOTT 模式下 RES 表的 RES_ID 列中包含 100002 的所有事務(wù)。 您還可以使用該特性掘出針對該數(shù)據(jù)庫執(zhí)行的 DDL 命令。要實現(xiàn)這一目的,選擇 Query Filter 部分中的單選按鈕 View DDL Only 即可。 收回選定的事務(wù) 在檢查一個事務(wù)時,您想怎樣處理這個事務(wù)?一種想法是將其撤消,因為此事務(wù)的執(zhí)行有誤,這或許是您查找該事務(wù)的首要原因。這非常簡單。如果該事務(wù)是一個插入,您只需將其刪除即可;如果它是一個更新,則撤消會將該行還原至前一個值。 然而,請仔細(xì)觀察本例中使用的事務(wù)。第一個事務(wù)插入了一行。第二個事務(wù)更新了剛插入的行,而第三個事務(wù)將那一行刪除了。第一個事務(wù)(插入)就是您要收回的事務(wù)。但是,問題是,那一行已經(jīng)被后續(xù)的事務(wù)刪除了,那么在本例中撤消事務(wù)是什么呢? 這就是 Oracle 數(shù)據(jù)庫 11g 中 Dependent Transaction 視圖特性的用途所在。單擊 Flashback Transaction。經(jīng)過一些搜索后,系統(tǒng)將顯示類似下圖的屏幕: 該屏幕將為您顯示相關(guān)事務(wù)以及更新和刪除?,F(xiàn)在,在收回事務(wù)時,您還可以收回其依賴項。 要實現(xiàn)這一目的,從下面的列表中選擇 Cascade 單選按鈕,然后單擊 OK 即可。 它會為您顯示所需收回的不同事務(wù)。單擊事務(wù) ID 查看 Oracle 將執(zhí)行什么 SQL 語句來撤消這個事務(wù)。 例如,要撤消插入,Oracle 必須執(zhí)行刪除,如上圖所示。如果點(diǎn)擊下一個事務(wù)(就在它的下面),您將看到收回下一個事務(wù)所需的詳細(xì)操作: 這樣,您就了解了操作構(gòu)思。單擊 Submit,所有這些事務(wù)都將一次性全部回滾。這是撤消事務(wù)及其依賴項最徹底的方法。 命令行界面 如果您無權(quán)訪問企業(yè)管理器怎么辦?或者也許您想通過腳本來完成這一切,那該怎么辦?程序包 DBMS_FLASHBACK(Oracle 數(shù)據(jù)庫 10g 中也提供該程序包)新增了一個名為 TRANSACTION_BACKOUT 的過程。這個過程超載,因此您必須將值傳遞給命名參數(shù),如下所示。 declare trans_arr xid_array; begin trans_arr := xid_array('030003000D040000','F30003000D04010'); dbms_flashback.transaction_backout ( numtxns => 1, xids => trans_arr, options => dbms_flashback.cascade ); end; xid_array 類型也是 Oracle 數(shù)據(jù)庫 11g 的新增內(nèi)容。它用來向該過程傳遞一系列事務(wù)標(biāo)識符。 LogMiner 的其他改進(jìn) 如果您一直使用 XML Type 作為數(shù)據(jù)類型,那么在 Oracle 數(shù)據(jù)庫 11g 中您更有理由使用它,您會很高興地看到 LogMiner 也可以挖掘 XML 數(shù)據(jù)。XML 數(shù)據(jù)在 SQL_REDO 和 SQL_UNDO 列中都有顯示。 啟動 LogMiner 時,您可以設(shè)置選項 SKIP_CORRUPTION,它會跳過重做日志中的受損塊。因此,即使部分?jǐn)?shù)據(jù)損壞了,您也可以回收重做日志里的有效數(shù)據(jù)。 以下是這一改進(jìn)語法的用法: begin dbms_logmnr.start_logmnr( options => dbms_logmnr.skip_corruption ) ; end; 閃回數(shù)據(jù)存檔 Oracle9i 數(shù)據(jù)庫第 2 版以閃回查詢的形式引入了眾所周知的時間機(jī)器。閃回查詢允許您選擇更改前的數(shù)據(jù)。例如,如果您將一個值從 100 改為 200 并將其提交,即使更改已經(jīng)提交了,您仍然可以選擇兩分鐘前的值。這種技術(shù)使用了還原段中更改前的數(shù)據(jù)。在 Oracle 數(shù)據(jù)庫 10g 中,這項功能通過引入閃回版本查詢得到增強(qiáng),您甚至可以將某一行的更改追溯到還原段所能提供的最久遠(yuǎn)的更改狀態(tài)。 但是,這里存在一個小問題:數(shù)據(jù)庫回收后,還原數(shù)據(jù)被清除了,隨之更改前的值也消失了。即使不回收數(shù)據(jù)庫,數(shù)據(jù)也可能因時間太長而退出還原段為新更改讓出空間。 由于 11g 之前的閃回操作依賴于還原數(shù)據(jù),而還原數(shù)據(jù)的可用時間短暫,您無法真正長期使用這些數(shù)據(jù)或者將其用于審計之類較永久的記錄。作為變通手段,我們通過編寫觸發(fā)器來長期記錄數(shù)據(jù)庫的更改。 不過,不要感到失望。在 Oracle 數(shù)據(jù)庫 11g 中,閃回數(shù)據(jù)存檔結(jié)合了兩者的優(yōu)勢:它既提供閃回查詢的簡易性與功能性,又不像還原數(shù)據(jù)一樣依賴臨時存儲。它在更加永久的位置(即閃回恢復(fù)區(qū))記錄更改。 我們來看一個示例。(注:您需要激活自動撤消管理,這樣閃回數(shù)據(jù)存檔才能發(fā)揮作用。)首先,創(chuàng)建一個閃回數(shù)據(jù)存檔,如下所示: SQL> create flashback archive near_term 2 tablespace far_near_term 3 retention 1 month 4 / Flashback archive created. 關(guān)于時間,先不用管術(shù)語“保留”的意義,我們稍后再討論。(這是記錄更改的位置。)存檔在表空間 far_near_term 中創(chuàng)建好了。 假設(shè)您需要記錄表 TRANS 的更改。那么,您只需啟用該表的閃回數(shù)據(jù)存檔狀態(tài),開始在存檔中記錄更改即可。 SQL> alter table trans flashback archive near_term; Table altered. 這會將表置于閃回數(shù)據(jù)存檔模式?,F(xiàn)在,該表中的所有行更改都將受到永久跟蹤。我們來看一個演示。 首先,選擇該表的一個具體行。 SQL> select txn_amt from trans where trans_id = 2; TXN_AMT ---------- 19325.67 SQL> update trans set txn_amt = 2000 where trans_id = 2; 1 row updated. SQL> commit; Commit complete. 現(xiàn)在,如果您選擇了該行,則這一列將始終顯示 2000。要查找早先某一時間點(diǎn)時的值,您可以使用閃回查詢,如下所示: elect txn_amt from trans as of timestamp to_timestamp ('07/18/2007 12:39:00','mm/dd/yyyy hh24:mi:ss') where trans_id = 2; TXN_AMT ---------- 19325.67 現(xiàn)在,隔一段時間,當(dāng)還原數(shù)據(jù)從還原段中清除后,再次查詢這個閃回數(shù)據(jù): select txn_amt from trans as of timestamp to_timestamp ('07/18/2007 12:39:00','mm/dd/yyyy hh24:mi:ss') where trans_id = 2; 結(jié)果返回:19325.67. 還原數(shù)據(jù)已經(jīng)清除了,那么這個數(shù)據(jù)來自何處呢? 我們問問 Oracle。您可以使用自動跟蹤來查看執(zhí)行計劃: SQL> set autotrace traceonly explain SQL> select txn_amt 2 from trans 3 as of timestamp to_timestamp ('07/18/2007 12:39:00','mm/dd/yyyy hh24:mi:ss') 4 where trans_id = 2; Execution Plan ---------------------------------------------------------- Plan hash value: 535458644 ---------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 52 | 10 (10)| 00:00:01 | | | 1 | VIEW | | 2 | 52 | 10 (10)| 00:00:01 | | | 2 | UNION-ALL | | | | | | | |* 3 | FILTER | | | | | | | | 4 | PARTITION RANGE SINGLE| | 1 | 52 | 3 (0)| 00:00:01 | 1 | 1 |* 5 | TABLE ACCESS FULL | SYS_FBA_HIST_68909 | 1 | 52 | 3 (0)| 00:00:01 | 1 | 1 |* 6 | FILTER | | | | | | | |* 7 | HASH JOIN OUTER | | 1 | 4053 | 10 (10)| 00:00:01 | | |* 8 | TABLE ACCESS FULL | TRANS | 1 | 38 | 6 (0)| 00:00:01 | | | 9 | VIEW | | 2 | 8030 | 3 (0)| 00:00:01 | | |* 10 | TABLE ACCESS FULL | SYS_FBA_TCRV_68909 | 2 | 8056 | 3 (0)| 00:00:01 | | ------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(NULL IS NOT NULL) 5 - filter("TRANS_ID"=2 AND "ENDSCN">161508784336056 AND "ENDSCN"<=1073451 AND ("STARTSCN" IS NULL OR "STARTSCN"<=161508784336056)) 6 - filter("F"."STARTSCN"<=161508784336056 OR "F"."STARTSCN" IS NULL) 7 - access("T".ROWID=("F"."RID"(+))) 8 - filter("T"."VERSIONS_STARTSCN" IS NULL AND "T"."TRANS_ID"=2) 10 - filter(("ENDSCN" IS NULL OR "ENDSCN">1073451) AND ("STARTSCN" IS NULL OR "STARTSCN"<1073451)) Note ----- - dynamic sampling used for this statement 該輸出回答了我們的疑問“這個數(shù)據(jù)來自何處?”,數(shù)據(jù)來自表 SYS_FBA_HIST_68909,這是您先前為那個表定義的閃回存檔中的某個位置。您可以查看這個表,但是 Oracle 不支持在那里直接查看數(shù)據(jù)。不過,我覺得您也沒有必要那樣做。 存檔中的數(shù)據(jù)能保留多長時間呢?這就是保留期限的作用了。數(shù)據(jù)可以在該期限內(nèi)一直保留。保留期限過后,當(dāng)有新的數(shù)據(jù)進(jìn)來時,較老的數(shù)據(jù)將被清除。您也可以自己清除數(shù)據(jù),例如: alter flashback archive near_term purge before scn 1234567; 管理閃回存檔 您可以在一個存檔中添加多個表空間。反過來,您也可以從一個存檔中刪除表空間。如果您打算使用已經(jīng)具有其他用戶數(shù)據(jù)的表空間,則存在閃存數(shù)據(jù)存檔數(shù)據(jù)將表空間擠滿的風(fēng)險,從而沒有空間供用戶數(shù)據(jù)使用。為了降低這種風(fēng)險,您可以設(shè)置存檔在表空間內(nèi)可以占用的空間定額。您可以通過以下語句設(shè)置定額: alter flashback archive near_term modify tablespace far_near_term quota 10M; 您可以通過查詢字典視圖查看哪些表開啟了閃回數(shù)據(jù)存檔: SQL> select * from user_flashback_archived_tables; TABLE_NAME OWNER_NAME ------------------------------ ------------------ FLASHBACK_ARCHIVE_NAME ------------------------------------------------- TRANS ARUP NEAR_TERM 您可以通過查詢字典視圖查找存檔: sql> select * from flashback_archives; FLASHBACK_ARCHI FLASHBACK_ARCHIVE# RETENTION_IN_DAYS PURGE_SCN STATUS --------------- ------------------ ----------------- ---------- ------- NEAR_TERM 1 30 1042653 MED_TERM 2 365 1042744 LONG_TERM 3 1825 1042838 使用多個存檔可以使您在不同情況下通過獨(dú)創(chuàng)方式對其進(jìn)行應(yīng)用。例如,某酒店企業(yè)的數(shù)據(jù)庫可能需要保留一年的預(yù)定信息,而需要保留三年的付款信息。那么,您可以定義多個帶有不同保留策略的存檔,然后將其分配給各個表。或者,如果有統(tǒng)一的保留策略,您可以只定義一個存檔并將其設(shè)為默認(rèn)選項。 alter flashback archive near_term set default; 當(dāng)某個表不需要存檔時,您可以通過以下命令將存檔關(guān)閉: alter table trans no flashback archive; 如您所見,您一行代碼都不需要編寫就實現(xiàn)了一個功能強(qiáng)大的更改記錄系統(tǒng)。 與常規(guī)審計的區(qū)別 閃回數(shù)據(jù)存檔與常規(guī)審計的區(qū)別是什么?首先,后者需要將 audit_trail 參數(shù)設(shè)置為 DB 或 DB_EXTENDED,并將審計線索寫入 SYSTEM 表空間的 AUD$ 表中。閃回數(shù)據(jù)存檔可在任何表空間上(或多個表空間上,甚至存儲用戶數(shù)據(jù)的表空間的某些部分上)進(jìn)行定義,因此可以在更廉價的存儲設(shè)備上進(jìn)行定義。 其次,審計以自主事務(wù)為基礎(chǔ),會造成一些性能開銷。閃回數(shù)據(jù)存檔由專用后臺進(jìn)程 FBDA 編寫,因此對性能的影響較小。 最后,閃回數(shù)據(jù)存檔可定期自動清除。審計線索必須通過人工進(jìn)行維護(hù)。 使用案例 閃回數(shù)據(jù)存檔具有多種便捷的用途。這里給出部分用途: - 審計以記錄數(shù)據(jù)的更改方式
- 支持應(yīng)用程序撤消更改(糾正錯誤)
- 調(diào)試數(shù)據(jù)的更改方式
- 遵守某些規(guī)定,不準(zhǔn)數(shù)據(jù)在某段時間內(nèi)出現(xiàn)更改。閃回數(shù)據(jù)存檔不屬于常規(guī)表,所以普通用戶無法對其進(jìn)行更改操作。
- 可在更廉價的存儲設(shè)備上記錄審計線索,因而能以較低的成本保留更多的信息。
結(jié)論 錯誤發(fā)生了,但是現(xiàn)在您可以自信地斷定,您能夠識別引起錯誤的具體更改,而且您擁有通過事務(wù)收回完全回滾這些錯誤的工具。但是,您的方法不再局限于從存檔的和在線的重做日志中挖掘更改,更改已經(jīng)永久地記錄在了閃回存檔中。現(xiàn)在,只需通過幾個命令就可以針對任何實際目的在閃回恢復(fù)區(qū)審計更改了。 返回到“Oracle 數(shù)據(jù)庫 11g:面向 DBA 和開發(fā)人員的重要特性”主頁 Arup Nanda (arup@proligence.com) 是 Starwood Hotels and Resorts 的數(shù)據(jù)庫系統(tǒng)經(jīng)理,從事 Oracle 的 DBA 職業(yè)十多年,并且在 2003 年由《Oracle 雜志》 評選為“年度 DBA”。Arup 經(jīng)常在 Oracle 相關(guān)活動中發(fā)表演講,并在 Oracle 相關(guān)雜志上撰寫文章,他是紐約 Oracle 用戶群執(zhí)行委員會的成員,并且是一位 Oracle ACE。他與其他人合作編寫了《Oracle 隱私安全性審計》(Rampant TechPress 出版)一書。 |