- 精通Oracle 12c 數(shù)據(jù)庫管理
- 王榮鑫
- 3002字
- 2019-07-30 18:03:58
3.3 實例內存區(qū)
由于內存結構和進程結構關系較緊密,進程會作用到對應的內存區(qū)域,比如數(shù)據(jù)庫寫入器作用到數(shù)據(jù)庫緩沖區(qū)緩存中,日志寫入器會作用到日志緩沖區(qū),所以內存結構和進程結構會相互配合地進行描述。
Oracle實例內存結構由SGA(系統(tǒng)全局區(qū))和PGA(用戶全局區(qū))兩部分組成。SGA是一塊共享的內存區(qū)域,也是最大的一塊內存區(qū)域;PGA則是用戶會話專有的內存區(qū)域,每個會話在服務器端都有一塊專有的內存區(qū)域就是PGA。本文主要對SGA進行分析描述。SGA組成如圖3-3所示。

圖3-3 SGA內存結構
3.3.1 數(shù)據(jù)庫高速緩沖區(qū)
緩沖區(qū)緩存是Oracle用來執(zhí)行SQL語句的工作區(qū)域,在更新數(shù)據(jù)時,用戶會話不會直接去更新磁盤上的數(shù)據(jù)。
【示例3-1】查詢語句
select ename,salary from emp where name='SAM';
如示例3-1這樣一條簡單的查詢語句,Oracle是如何處理的呢?首先,當用戶提交了該條sql語句,由對應的用戶進程(比如常用的sql developer)將其發(fā)送給服務器,監(jiān)聽程序監(jiān)聽到該條請求,會為其建立一個對應的服務器進程,然后服務器進程會先掃描緩沖區(qū)中有沒有包含關鍵行("SAM")的數(shù)據(jù)塊,如果有,這就算一次緩存命中了,然后相關行會傳輸?shù)絇GA進行進一步處理,最終經(jīng)過格式化后展示給用戶;如果沒有命中,那么服務器進程會首先將對應行復制到緩沖區(qū)內,然后返回給客戶端。
DML(insert, update, delete)操作同理,加入用戶發(fā)送一條update語句,服務進程依然先去掃描緩沖區(qū),如果緩存命中,則直接更新,數(shù)據(jù)變臟;如果沒有命中,由服務器進程將對應數(shù)據(jù)塊先從磁盤上復制到緩沖區(qū)內,再進行更新操作。
如果緩沖區(qū)存儲的塊和磁盤上的塊不一致,該緩沖區(qū)就叫作“臟緩沖區(qū)”,臟緩沖區(qū)最終會由數(shù)據(jù)庫寫入器(DBWn)寫入到磁盤中去。
數(shù)據(jù)庫寫入器是Oracle的一個后臺進程。所謂后臺進程,是相對于前臺進程(服務器進程)來講的。DBWn的"n"意味著一個實例是可以有多個數(shù)據(jù)庫寫入器的。簡而言之,DBWn的作用就是將變臟了的緩沖區(qū)從數(shù)據(jù)庫緩沖區(qū)緩存中寫入到磁盤中的數(shù)據(jù)文件中去。
數(shù)據(jù)庫緩沖區(qū)緩存區(qū)域和數(shù)據(jù)庫寫入器是比較重要的概念,別的數(shù)據(jù)庫產(chǎn)品像MySQL也都有對應的實現(xiàn),只不過叫法不一樣罷了。了解時,要時刻意識到會話是不會直接更新磁盤數(shù)據(jù)的,會話的更新、插入、刪除包括查詢等都是先作用到緩沖區(qū)上,隨后,DBWn會將其中的臟緩沖區(qū)轉儲到磁盤上去。
那么DBWn什么時候寫入呢?DBWn是一個比較懶的進程,會盡可能少地進行寫入,在以下四種情況下會執(zhí)行寫入:
? 沒有任何可用緩沖區(qū)(不得不寫)。
? 臟緩沖區(qū)過多。
? 3秒超時(最晚3秒會執(zhí)行一次寫入)。
? 遇到檢查點,即checkPoint(檢查點)。檢查點是一個Oracle事件,遇到檢查點,DBWn會執(zhí)行寫入。比如,實例有序關閉時會有檢查點,DBWn會將所有臟緩沖區(qū)寫入到磁盤上去,這很容易理解,要保持數(shù)據(jù)文件的一致性。
從上述DBWn的幾個寫入時機可以看出,DBWn的寫入不直接依賴于會話的更新操作。不是一有臟緩沖區(qū),它就執(zhí)行寫入。而且,DBWn執(zhí)行寫入跟commit操作也沒有任何關系,不要以為commit操作的影響結果會實時流入到磁盤中去。
DBWn采用極懶算法進行寫入,原因應該要清楚:頻繁的磁盤IO對系統(tǒng)的壓力很大,如果DBWn很積極地去寫入磁盤,那對系統(tǒng)性能的影響就太大了,換個角度想,如果DBWn很勤快地寫磁盤,那么數(shù)據(jù)庫緩沖區(qū)存在的意義也就不大了。
當然,說到這里,用戶可能會意識到一個問題,DBWn如此懶地進行數(shù)據(jù)轉儲,如果在某一時刻,數(shù)據(jù)庫緩沖區(qū)緩存內存在著大量的臟緩沖區(qū)(在生產(chǎn)環(huán)境中,這是常態(tài)),也就是有大量的未commit和已commit的數(shù)據(jù)還在內存中,沒有持久化到磁盤中,然后突然系統(tǒng)斷電了,這種情況下,數(shù)據(jù)是不是就丟掉了?數(shù)據(jù)當然不會丟失,這就引出了重做日志(redo log)的概念。接下來,就來談談對應重做日志的內存結構和后臺進程。
3.3.2 日志緩沖區(qū)
當用戶執(zhí)行一些DML操作(INSERT、UPDATE、DELETE)時,數(shù)據(jù)塊發(fā)生改變,產(chǎn)生的變更向量則會寫入到重做日志文件中去。有了這些記錄,當系統(tǒng)由于斷電等因素突然宕掉,數(shù)據(jù)庫緩沖區(qū)緩存內的大量臟數(shù)據(jù)還沒來得及寫入到數(shù)據(jù)文件中去,在重新啟動時,會有一個實例恢復的過程,在此過程中就應用了重做日志記錄來使數(shù)據(jù)保持一致;或者數(shù)據(jù)庫遭遇了物理損壞,比如磁盤損壞了,此時可以通過Oracle的備份恢復工具(如RMAN)進行數(shù)據(jù)恢復,原理就是提取備份集然后應用重做日志文件中的變更記錄。
日志緩沖區(qū)是一塊比較小的內存區(qū)域,用來短期存儲將寫入到磁盤中的重做日志文件中的變更向量的。日志緩沖區(qū)存在的意義依然是為了減少磁盤IO,減少用戶的等待時間。試想下,如果每一次用戶DML操作都要進行等待重做記錄被寫入到磁盤中去,用戶體驗會比較差。
日志的寫入工作是由日志寫入器來負責完成的。顧名思義,日志寫入器(LGWR)就是把日志緩沖區(qū)內的內容寫入到磁盤的重做日志文件中去,相比數(shù)據(jù)庫寫入器(DBWn),日志寫入器就勤快多了。
以下三種情況LGWR會執(zhí)行寫入:
(1)Commit時寫入:因為DBWn的寫入和commit沒有任何關系,如果commit時數(shù)據(jù)庫沒有任何記錄,那數(shù)據(jù)就真的丟失了,Oracle的重做日志就是為了保證數(shù)據(jù)安全而存在的,commit時,會話會先掛起,等待LGWR將這些記錄寫入到磁盤上的重做日志文件中,才會通知用戶提交完成。所以,LGWR在commit時執(zhí)行寫入,是為了確保事務永不丟失。
(2)日志緩沖區(qū)的占用率達到1/3。
(3)DBWn要寫入臟緩沖區(qū)前,這個寫入是為了數(shù)據(jù)回滾考慮的。DBWn完全可能寫入還沒提交的事務(參照上面提到的寫入時機),那如何保證事務回滾呢?
首先要知道,DBWn除了寫入實際的數(shù)據(jù),還會寫入撤銷數(shù)據(jù)。簡單說,事務回滾需要撤銷數(shù)據(jù),在寫入撤銷數(shù)據(jù)前,會先寫入針對撤銷數(shù)據(jù)的日志記錄,若用戶要進行事務回滾,就可以應用這些日志記錄來構造撤銷數(shù)據(jù),然后進行回滾。
下面對這兩塊最重要的內存區(qū)域和對應的后臺進程做個總結:數(shù)據(jù)庫緩沖區(qū)緩存和日志緩沖區(qū)都是為了提高性能,避免頻繁IO而存在的。日志緩沖區(qū)相比數(shù)據(jù)庫緩沖區(qū)緩存要小得多,并且不能進行自動管理,對于日志緩沖區(qū)的修改需要重啟實例,數(shù)據(jù)庫緩沖區(qū)緩存可進行自動管理。作用在數(shù)據(jù)庫緩沖區(qū)緩存上的DBWn進程,為了避免頻繁的磁盤IO導致系統(tǒng)性能下降,會盡可能少地執(zhí)行寫入,且DBWn的寫入和commit操作沒有任何關系。作用在日志緩沖區(qū)上的LGWR進程,則會非常積極地進行寫入,一般情況下,它幾乎是實時地將重做日志記錄轉儲到磁盤中去。LGWR是Oracle體系結構中最大的瓶頸之一。DML的速度不可能超過LGWR將變更向量寫入磁盤的速度。
下面繼續(xù)講解其他的內存區(qū)域和后臺進程。
3.3.3 共享池
共享池是最復雜的SGA結構,它有許多子結構,下面來看看常見的幾個共享池組件。
(1)庫緩存:庫緩存這塊內存區(qū)域會按已分析的格式緩存最近執(zhí)行的代碼。這樣,同樣的sql代碼多次執(zhí)行時,就不用重復地去進行代碼分析,可以在很大程度上提高系統(tǒng)性能。
(2)數(shù)據(jù)字典緩存:存儲Oracle中的對象定義(表、視圖、同義詞、索引等數(shù)據(jù)庫對象)。這樣在分析sql代碼時,就不用頻繁去磁盤上讀取數(shù)據(jù)字典中的數(shù)據(jù)了。
(3)PL/SQL區(qū):緩存存儲過程、函數(shù)、觸發(fā)器等數(shù)據(jù)庫對象,這些對象都存儲在數(shù)據(jù)字典中,通過將其緩存到內存中,可以在重復調用時提高性能。
(4)大池:大池是一個可選的內存區(qū)域。前面提到專有服務器連接和共享服務器連接,如果數(shù)據(jù)庫采用了共享服務器連接模式,則要使用到大池;RMAN(Oracle的高級備份恢復工具)備份數(shù)據(jù)也需要大池。
3.3.4 Java池和流池
Java池和流池因為實際的企業(yè)環(huán)境中使用的比較少,這里不做過多的介紹。Oracle的很多選項是使用Java寫的,Java池用作實例化Java對象所需的堆空間。從重做日志中提取變更記錄的進程和應用變更記錄的進程會用到流池(如實例不正常關閉,譬如斷電導致實例關閉,在重啟時,Oracle會自動執(zhí)行實例恢復過程,在此過程需要提取重做日志記錄和應用重做日志兩個動作)。
- Podman實戰(zhàn)
- C++ 從入門到項目實踐(超值版)
- 網(wǎng)站構建技術
- RabbitMQ Cookbook
- Internet of Things with ESP8266
- 大話Java:程序設計從入門到精通
- Backbone.js Testing
- Go語言入門經(jīng)典
- PhoneGap 4 Mobile Application Development Cookbook
- ANSYS FLUENT 16.0超級學習手冊
- Learn Linux Quickly
- Mastering React Test:Driven Development
- Office VBA開發(fā)經(jīng)典:中級進階卷
- 軟件工程基礎
- Magento 2 Development Essentials