博文轉自:http://blog.csdn.net/hzhsan/article/details/9719307html
這一點很重要,之因此要了解並掌握這個事實,緣由之一是:這樣你就能心無芥蒂地讓事務有足夠的大小。一種錯誤的信念認爲分批提交能夠節省稀有的系統資源,而實際上這只是增長了資源的使用。若是隻在必要時才提交(即邏輯工做單元結束時),不只能提升性能,還能減小對共享資源的競爭(日誌文件、各類內部閂等)。sql
分批提交COMMIT的開銷存在兩個因素:數據庫
顯然會增長與數據庫的往返通訊。若是每一個記錄都提交,生成的往返通訊量就會大得多。編程
每次提交時,必須等待redo寫至磁盤。這會致使「等待」。在這種狀況下,等待稱爲「日誌文件同步」(log file sync)。緩存
爲何COMMIT的響應時間至關「平」,而不論事務大小呢?在數據庫中執行COMMIT以前,困難的工做都已經作了。咱們已經修改了數據庫中的數據,因此99.9%的工做都已經完成。例如,已經發生了如下操做:安全
已經在SGA中生成了undo塊。session
已經在SGA中生成了已修改數據塊。數據結構
已經在SGA中生成了對於前兩項的緩存redo。oracle
取決於前三項的大小,以及這些工做花費的時間,前面的每一個數據(或某些數據)可能已經刷新輸出到磁盤。異步
已經獲得了所需的所有鎖。
執行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)的時間或者說提交所用的時間都基本相同。