博文轉自:http://blog.csdn.net/hzhsan/article/details/9719307
這一點很重要,之所以要了解並掌握這個事實,原因之一是:這樣你就能心無芥蒂地讓事務有足夠的大小。一種錯誤的信念認為分批提交可以節省稀有的系統資源,而實際上這只是增加了資源的使用。如果只在必要時才提交(即邏輯工作單元結束時),不僅能提高效能,還能減少對共享資源的競爭(日誌檔案、各種內部閂等)。
分批提交COMMIT的開銷存在兩個因素:
顯然會增加與資料庫的往返通訊。如果每個記錄都提交,生成的往返通訊量就會大得多。
每次提交時,必須等待redo寫至磁碟。這會導致“等待”。在這種情況下,等待稱為“日誌檔案同步”(log file sync)。
為什麼COMMIT的響應時間相當“平”,而不論事務大小呢?在資料庫中執行COMMIT之前,困難的工作都已經做了。我們已經修改了資料庫中的資料,所以99.9%的工作都已經完成。例如,已經發生了以下操作:
已經在SGA中生成了undo塊。
已經在SGA中生成了已修改資料塊。
已經在SGA中生成了對於前兩項的快取redo。
取決於前三項的大小,以及這些工作花費的時間,前面的每個資料(或某些資料)可能已經重新整理輸出到磁碟。
已經得到了所需的全部鎖。
執行COMMIT時,餘下的工作只是:
為事務生成一個SCN。如果你還不熟悉SCN,起碼要知道,SCN是Oracle使用的一種簡單的計時機制,用於保證事務的順序,並支援失敗恢復。SCN 還用於保證資料庫中的讀一致性和檢查點。可以把SCN看作一個鐘擺,每次有人COMMIT時,SCN都會增1.
LGWR將所有餘下的快取重做日誌條目寫到磁碟,並把SCN記錄到線上重做日誌檔案中。這一步就是真正的COMMIT。如果出現了這一步,即已經提交。事務條目會從V$TRANSACTION中“刪除”,這說明我們已經提交。
V$LOCK中記錄這我們的會話持有的鎖,這些所都將被釋放,而排隊等待這些鎖的每一個人都會被喚醒,可以繼續完成他們的工作。
如果事務修改的某些塊還在緩衝區快取中,則會以一種快速的模式訪問並“清理”。塊清除(Block cleanout)是指清除儲存在資料庫塊首部的與鎖相關的資訊。實質上講,我們在清除塊上的事務資訊,這樣下一個訪問這個塊的人就不用再這麼做了。我們採用一種無需生成重做日誌資訊的方式來完成塊清除,這樣可以省去以後的大量工作(在下面的“塊清除”一節中將更全面地討論這個問題)。
可以看到,處理COMMIT所要做的工作很少。其中耗時最長的操作要算LGWR執行的活動(一般是這樣),因為這些磁碟寫是物理磁碟I/O。不過,這裡LGWR花費的時間並不會太多,之所以能大幅減少這個操作的時間,原因是LGWR一直在以連續的方式重新整理輸出重做日誌緩衝區的內容。在你工作期間,LGWR並非快取這你做的所有工作;實際上,隨著你的工作的進行,LGWR會在後臺增量式地重新整理輸出重做日誌緩衝區的內容。這樣做是為了避免COMMIT等待很長時間來一次性重新整理輸出所有的redo。
因此,即使我們有一個長時間執行的事務,但在提交之前,它生成的許多快取重做日誌已經重新整理輸出到磁碟了(而不是全部等到提交時才重新整理輸出)。這也有不好的一面,COMMIT時,我們必須等待,直到尚未寫出的所有快取redo都已經安全寫到磁碟上才行。也就是說,對LGWR的呼叫是一個同步(synchronous)呼叫。儘管LGWR本身可以使用非同步I/O並行地寫至日誌檔案,但是我們的事務會一直等待LGWR完成所有寫操作,並收到資料都已在磁碟上的確認才會返回。
前面我提高過,由於某種原因,我們用的是一個Java程式而不是PL/SQL,這個原因就是 PL/SQL提供了提交時優化(commit-time optimization)。我說過,LGWR是一個同步呼叫,我們要等待它完成所有寫操作。在Oracle 10g Release 1及以前版本中,除PL/SQL以外的所有程式語言都是如此。PL/SQL引擎不同,要認識到直到PL/SQL例程完成之前,客戶並不知道這個PL /SQL例程中是否發生了COMMIT,所以PL/SQL引擎完成的是非同步提交。它不會等待LGWR完成;相反,PL/SQL引擎會從COMMIT呼叫立即返回。不過,等到PL/SQL例程完成,我們從資料庫返回客戶時,PL/SQL例程則要等待LGWR完成所有尚未完成的COMMIT。因此,如果在PL /SQL中提交了100次,然後返回客戶,會發現由於存在這種優化,你只會等待LGWR一次,而不是100次。這是不是說可以在PL/SQL中頻繁地提交呢?這是一個很好或者不錯的主意嗎?不是,絕對不是,在PL/SQ;中頻繁地提交與在其他語言中這樣做同樣糟糕。指導原則是,應該在邏輯工作單元完成時才提交,而不要在此之前草率地提交。
COMMIT是一個“響應時間很平”的操作,雖然不同的操作將生成不同大小的redo,即使大小相差很大或者說無論生成多少redo,但也並不會影響提交(COMMIT)的時間或者說提交所用的時間都基本相同。