程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> Oracle DB BUFFER寶典說明

Oracle DB BUFFER寶典說明

編輯:Oracle數據庫基礎

經過長時間學習Oracle,於是和大家分享一下,看完本文你肯定有不少收獲,希望本文能教會你更多東西。生成編譯代碼之後,接著下一步服務器進程要准備開始更新數據,服務器進程將到Oracle DB BUFFER中查找是否有相關對象的緩存數據,下面分兩個可能進行解釋:

如果沒有,服務器進程將在表頭部請求一些行鎖,如果成功加鎖,服務器進程將從數據文件中讀入這些行所在的第一個數據塊(db block)(DB BLOCK是ORACLE的最小操作單元,即使你想要的數據只是DB BLOCK中很多行中的一行或幾行,ORACLE也會把這個DB BLOCK中的所有行都讀入Oracle DB BUFFER中)放入Oracle DB BUFFER中空閒的區域或者覆蓋已被擠出LRU列表的非髒數據塊緩沖區,並且排列在LRU列表的頭部,如果這些非髒數據緩沖區寫完也不能滿足新數據的請求時,會立即觸發DBWN進程將髒數據列表中指向的緩沖塊寫入數據文件,並且清洗掉這些緩沖區,來騰出空間緩沖新讀入的數據,也就是在放入Oracle DB BUFFER之前也是要先申請Oracle DB BUFFER中的鎖存器,成功鎖定後,再寫入Oracle DB BUFFER,然後把這個塊的頭部事務列表及SCN信息及被影響的行數據原值寫入回滾段中,以便Oracle在ROLLBACK時可以利用當前數據塊和回滾段重構數據塊的"前映像"或遞歸重構出"前…前映像"來實現讀一致性。

然後在LOG BUFFER中生成日志,服務器程將該語句影響的被讀入Oracle DB BUFFER塊中的這些行的ROWID及將要更新的原值和新值及SCN等信息,以及回滾段的修改信息(即對某某回滾段地址進行了什麼修改)逐條的寫入REDO LOG BUFFER,在寫入REDO LOG BUFFER之前也是先請求REDO LOG BUFFER塊的鎖存器,成功鎖定之後才開始把REDOLOG寫入REDOLOG BUFFER。當寫入達到REDO LOG BUFFER大小的三分之一或寫入量達到1M或超過三秒後或發生檢查點時或者COMMIT時或者DBWN之前觸發LGWR進程,LGWR將把REDO LOG BUFFER中的數據寫入磁盤上的重做日志文件,已被寫入重做日志文件的REDO LOG BUFFER中的塊上的鎖存器被釋放,並可被後來寫入的信息所覆蓋。

回滾段其實也有BUFFER(在Oracle DB BUFFER中開辟),回滾段BUFFER中的內容是最早向磁盤上回滾段中寫的,寫完這些才會生成日志BUFFER中的內容,原因是日志中必須要記錄回滾段的新舊變化以便在恢復時從日志中的記錄的回滾段新舊變化對回滾段再次重寫,記住,REDO不光是對數據文件依據日志文件重寫,也要依據日志文件對回滾段重寫,而且重寫回滾段要先於重寫數據文件,要理解REDO就是重來一遍,所謂重來一遍就要跟正常的的先後順利一樣重做一遍(正常的操作中的順序就是先讀入Oracle DB BUFFER,寫回滾段buffer,後寫回滾段,後寫日志BUFFER,後改寫Oracle DB BUFFER,後寫日志最後寫數據文件)區別是REDO時不用再記日志了,這樣解釋後相信大家應該理解為什麼日志中也必須要記錄回滾段的信息了,只有這樣才可以對正常操作中的一個ROLLBACK動作進行恢復,即在REDO過程中利用即時重寫的數據塊和回滾段重構出一個當時適用的前鏡像來rollback。當一個重做日志文件寫滿後,LGWR將切換到下一個重做日志文件,重做日志文件也是循環工作方式。如果是歸檔模式,歸檔進程還將前一個寫滿的重做日志進程寫入歸檔日志文件。

當Oracle DB BUFFER改寫之後,服務器進程在髒數據列表中建立一條指向此Oracle DB BUFFER緩沖塊的指針。接著服務器進程會從數據文件讀入第二個數據塊(db block)重復以上讀入,建立回滾段,寫LOG BUFFER,改寫Oracle DB BUFFER,放入髒列表的動作,當髒數據列表達到一定長度時,DBWN進程將髒數據列表中指向的緩沖塊全部寫入數據文件,也就是釋放加在這些DB BUFER塊上的鎖存器,並在修改相應塊的頭部的SCN號(一次UPDATE操作只對應一個SCN)。前面說過DBWN動作之前會先觸發LGWR,這用以確保寫入數據文件的改變首先會被記錄在日志文件中。實際上ORACLE可以從數據文件中一次讀入多個塊放入Oracle DB BUFFER,然後再對這些塊建回滾段、再記日志等等,也就是每次操作的對象是DB BLOCK的復數,而不僅限於一次操作一個DB BLOCK,可以通過參數DB_FILE_MULTIBLOCK_READ_COUNT來設置一次讀入的塊的個數。注意,不管是否提交,用戶的所有更改都會被記錄在日志文件中,用戶級回滾的動作(rollback)沒有對應的COMMIT SCN。

在密集事務的情況下,LGWR可以把多個COMMIT產生的REDO條目批量寫入REDO LOG FILE,但每個COMMIT之間有十分之一秒的間隔,且會產生不同的COMMIT SCN。LGWR正常情況下是一個休眠進程,會被一定的條件觸發,喚醒,比如COMMIT就是一個喚醒條件,一旦LGWR被喚醒,LGWR將把喚醒時間點之前LOG BUFFER中產生的所有內容(從上次LGWR喚醒後到本次喚醒前之間寫入LOG BUFFER的內容)寫入LOG FILE,直到LGWR完成後,LGWR才可以被再次觸發,在LGWR觸發到完成期間所有對數據庫的操作仍然可以不間斷的加入LOG BUFFER。在這段時間內,LGWR不再接收其它條件的觸發,比如緊跟前一個COMMIT之後的其它COMMIT(復數)都要等待LGWR完成後才可以再次觸發LGWR,並在LGWR下次被觸發時,將積累的REDO BUFFER條目一次性寫入REDO LOG,後繼的COMMIT不會單個單個的觸發LGWR。

如果要查找的數據已緩存,則根據用戶的SQL操作類型決定如何操作,如果是SELECT則查看Oracle DB BUFFER塊的頭部是否有事務,如果有,將利用回滾段進行重構出一致性塊再讀取,如果沒有則比較SELECT的SCN與Oracle DB BUFFER塊頭部的SCN如果比自己大,仍然同上,如果比自己小則認這是一個非髒緩存,可以直接從這個Oracle DB BUFFER塊中讀取。如果是UPDATE則即使在Oracle DB BUFFER中找到一個沒有事務,而且SCN比自己小的非髒緩存數據塊,服務器進程仍然要到表的頭部對這條記錄申請加鎖,加鎖成功則進行後續動作,如果不成功,則要等待前面的進程解鎖後才能進行動作。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved