一. 進程概述php
先來看一下Oracle 11g 的架構圖。 算法
下載地址:Oracle 11g 架構圖 from Oracle University數據庫
進程是操做系統中的一種機制,它可執行一系列的操做步。在有些操做系統中使用做業(JOB)或任務(TASK)的術語。一個進程一般有它本身的專用存儲區。ORACLE進程的體系結構設計使性能最大。
ORACLE實例有兩種類型:單進程實例 和 多進程實例。
單進程ORACLE(又稱單用ORACLE)是一種數據庫系統,一個進程執行所有ORACLE代碼。因爲ORACLE部分和客戶應用程序不能分別以進程執行,因此ORACLE的代碼和用戶的數據庫應用是單個進程執行。在單進程環境下的ORACLE 實例,僅容許一個用戶可存取。例如在MS-DOS上運行ORACLE 。
多進程ORACLE實例(又稱多用戶ORACLE)使用多個進程來執行ORACLE的不一樣部分 ,對於每個鏈接的用戶都有一個進程。
在多進程系統中,進程分爲兩類:用戶進程 和ORACLE進程。當一用戶運行一應用程序,如PRO*C程序或一個ORACLE工具(如SQL*PLUS),爲用戶運行的應用創建一個用戶進程。緩存
ORACLE進程又分爲兩類:服務器進程 和 後臺進程。安全
服務器進程用於處理鏈接到該實例的用戶進程的請求。當應用和ORACELE是在同一臺機器上運行,而再也不經過網絡,通常將用戶進程和它相應的服務器進程組合成單個的進程,可下降系統開銷。然而,當應用和ORACLE運行在不一樣的機器上時,用戶進程通過一個分離服務器進程與ORACLE通訊。它可執行下列任務:
1) 對應用所發出的SQL語句進行語法分析和執行。
2) 從磁盤(數據文件)中讀入必要的數據塊到SGA的共享數據庫緩衝區(該塊不在緩衝區時)。
3) 將結果返回給應用程序處理。
系統爲了使性能最好和協調多個用戶,在多進程系統中使用一些附加進程,稱爲後臺進程。在許多操做系統中,後臺進程是在實例啓動時自動地創建。一個ORACLE實例能夠有許多後臺進程,但它們不是一直存在。服務器
後臺進程有:
DBWR(Database Write) : 數據庫寫入程序
LGWR(Log Write) : 日誌寫入程序
CKPT(Checkpoint) : 檢查點
SMON (System Monitor): 系統監控
PMON(Process Monitor) : 進程監控
ARCH(Archive) : 歸檔
RECO : 恢復
LCKn : 封鎖;
這是RAC 環境啓動時,各個進程的啓動順序:網絡
PMON started with pid=2, OS id=18042架構
DIAG started with pid=3, OS id=18044併發
PSP0 started with pid=4, OS id=18051oracle
LMON started with pid=5, OS id=18053
LMD0 started with pid=6, OS id=18055
LMS0 started with pid=7, OS id=18057
MMAN started with pid=8, OS id=18061
DBW0 started with pid=9, OS id=18063
LGWR started with pid=10, OS id=18065
CKPT started with pid=11, OS id=18067
SMON started with pid=12, OS id=18069
RECO started with pid=13, OS id=18071
CJQ0 started with pid=14, OS id=18073
MMON started with pid=15, OS id=18075
MMNL started with pid=16, OS id=18077
每一個後臺進程與ORACLE數據庫的不一樣部分交互。 其中SMON、PMON、DBWn、CKPT、LGWR 是五個必須的ORACLE後臺進程。
二. 進程詳細說明
1. DBWR進程
該進程執行將緩衝區寫入數據文件,是負責緩衝存儲區管理的一個ORACLE後臺進程。當緩衝區中的一緩衝區被修改,它被標誌爲「弄髒」,DBWR的主要任務是將「弄髒」的緩衝區寫入磁盤,使緩衝區保持「乾淨」。因爲緩衝存儲區的緩衝區填入數據庫或被用戶進程弄髒,未用的緩衝區的數目減小。當未用的緩衝區降低到不多,以至用戶進程要從磁盤讀入塊到內存存儲區時沒法找到未用的緩衝區時,DBWR將管理緩衝存儲區,使用戶進程總可獲得未用的緩衝區。
ORACLE採用LRU(LEAST RECENTLY USED)算法(最近最少使用算法)保持內存中的數據塊是最近使用的,使I/O最小。
觸發DBWR進程的條件有:
1. DBWR超時,大約3秒
2. 系統中沒有多餘的空緩衝區來存放數據
3. CKPT 進程觸發DBWR
在有些平臺上,一個實例可有多個DBWR。在這樣的實例中,一些塊可寫入一磁盤,另外一些塊可寫入其它磁盤。
2. LGWR進程
該進程將日誌緩衝區寫入磁盤上的一個日誌文件,它是負責管理日誌緩衝區的一個ORACLE後臺進程。
觸發LGWR進程的條件有:
1. 用戶提交
2. 有1/3重作日誌緩衝區未被寫入磁盤
3. 有大於1M的重作日誌緩衝區未被寫入磁盤
4. 3秒超時
5. DBWR 須要寫入的數據的SCN大於LGWR記錄的SCN,DBWR 觸發LGWR寫入。
日誌緩衝區是一個循環緩衝區。當LGWR將日誌緩衝區的日誌項寫入日誌文件後,服務器進程可將新的日誌項寫入到該日誌緩衝區。LGWR 一般寫得很快,可確保日誌緩衝區總有空間可寫入新的日誌項。
注意:有時候當須要更多的日誌緩衝區時,LWGR在一個事務提交前就將日誌項寫出,而這些日誌項僅當在之後事務提交後才永久化。
ORACLE使用快速提交機制,當用戶發出COMMIT語句時,一個COMMIT記錄當即放入日誌緩衝區,但相應的數據緩衝區改變是被延遲,直到在更有效時纔將它們寫入數據文件。當一事務提交時,被賦給一個系統修改號(SCN),它同事務日誌項一塊兒記錄在日誌中。因爲SCN記錄在日誌中,以至在並行服務器選項配置狀況下,恢復操做能夠同步。
3. CKPT進程
該進程在檢查點出現時,對所有數據文件的標題進行修改,指示該檢查點。負責在每當緩衝區高速緩存中的更改永久地記錄在數據庫中時,更新控制文件和數據文件中的數據庫狀態信息。
RedoLog Checkpoint 和 SCN關係
http://blog.csdn.net/tianlesoftware/archive/2010/01/25/5251916.aspx
Redo Log 和Checkpoint not complete
http://blog.csdn.net/tianlesoftware/archive/2009/12/01/4908066.aspx
4. SMON進程
SMON是Oracle數據庫相當重要的一個後臺進程, 該進程實例啓動時執行實例恢復,還負責清理再也不使用的臨時段, 是一種用於庫的「垃圾收集者」。在具備並行服務器選項的環境下,SMON對有故障CPU或實例進行實例恢復。SMON進程有規律地被呼醒,檢查是否須要,或者其它進程發現須要時能夠被調用。
它作的工做包括以下7件:
(1)清理臨時表空間:伴隨這「真正」的臨時表空間的出現,清理臨時表空間的瑣事已經減輕了,但它還沒徹底消失。例如,當創建一個索引,在建立期間分配給索引的擴展區被標誌爲TEMPORARY。若是Create Index會話因某些緣由異常中斷,SMON負責清理他們。其餘操做建立的臨時擴展區,SMON一樣會負責。
(2) 接合空閒空間:若是你正使用數據字典管理表空間,SMON負責把那些在表空間中空閒的而且互相是鄰近的extent接合成一個較大的空閒擴展區。這發生僅在帶有默認的pctincrease設置爲非零的存儲子句的字典管理表空間。
(3) 把對於不可用文件的事務恢復成活動狀態:它的角色相似在庫啓動期間。這時,由於文件不能用於恢復,SMON恢復在實例/崩潰恢復期間被跳過的故障事務。例如,文件可能已經在不可用或沒裝載的磁盤上。當文件變可用了,SMON將恢復它。
(4)執行一個RAC中故障節點的實例恢復:在一個oracle RAC配置中,當羣集中的一個庫實例失敗(例如,實例正執行的機器故障了),一些羣集中的其餘節點將開啓故障的實例的重作日誌文件,爲故障實例執行全部數據的恢復。
(5)清理OBJ$:OBJ$是一個包含庫中幾乎每個對象(表,索引,觸發器,視圖等等)的記錄的行級數據字典表。許屢次,這兒存在的記錄表明已刪對象,或表明不在這兒的對象,在oracle的信賴機制中被使用。SMON是刪除這些不在被須要的行的進程。
(6)收縮回滾段:SMON將執行回滾段的自動收縮到它的optimal尺寸,若是它被設置。
(7)「脫機」回滾段:對於DBA來,讓一個有active事務的回滾段,脫機或不可用,這事是可能的。Active事務正使用這脫機回滾段是可能的。在這狀況下,回滾不是真正的脫機;它被標誌爲「懸掛offline」。在後臺進程中,SMON將週期性盡力讓它真正脫機,直到成功。
SMON作許多其餘事情,譬如存在DBA_TAB_MONITORING視圖中的監控統計數據的洗刷,在SMON_SCN_TIME表中發現的時間戳定位信息的SCN的洗刷,等等。SMON在期間能消耗不少CPU,這應該被認爲是正常的。SMON週期性的甦醒(或被其餘後臺進程叫醒)來執行這些管家的家庭瑣事。
5. PMON進程
用於恢復失敗的數據庫用戶的強制性進程,它先獲取失敗用戶的標識,釋放該用戶佔有的全部數據庫資源。PMON有規律地被呼醒,檢查是否須要,或者其它進程發現須要時能夠被調用。
PMON進程負責在反常中斷的鏈接以後的清理工做。例如,若是因某些緣由專用服務「故障」或被kill掉,PMON就是負責處理(恢復或回滾工做)和釋放你的資源。 PMON將發出未提交工做的回滾,釋放鎖,和釋放分配給故障進程的SGA資源。除了在異常中斷以後的清理外,PMON監控其餘oracle後臺進程,若是有必要(和有可能)從新啓動他們。若是共享服務或一個分配器故障(崩潰),PMON將插手而且重啓另外一個(在清理故障進程以後)。
PMON將觀察全部Oracle進程,只要合適或重啓他們或停止進程。例如,在數據庫日誌寫進程事件中,LGWR故障,實例故障。這是一個嚴重的錯誤,最安全的處理方法就是去當即終止實例,讓正常的恢復處理數據。
PMON爲實例作的另外一件事是去使用Oracle TNS監聽器登記。當一個實例開啓的時候,PMON進程投出衆所周知的端口地址,除非指向其餘,來看是否監聽器正在開和運行着。衆所周知/默認端口是使用1521。
如今,若是監聽器在一些不一樣端口開啓會發生什麼?這種狀況,機制是相同的,除了監聽器地址須要被LOCAL_LISTENER參數明確指定。若是監聽器運行在庫實例開啓的時候,PMON和監聽器通信,傳到它相關參數,譬如服務器名和實例的負載度量。若是監聽器沒被開啓,PMON將週期性的試着和它聯繫來登記本身。
The background process PMON cleans up after failed processes by:
1. Rolling back the user’s current transaction
2. Releasing all currently held table or row locks
3. Freeing other resources currently reserved by the user
4. Restarts dead dispatchers
6. RECO進程
負責在分佈式數據庫環境中自動恢復那些失敗的分佈式事務,保證分佈式事務的一致性,在分佈式事務中,要麼同時commit,要麼同時rollback;
7. ARCH進程
該進程將已填滿的在線日誌文件拷貝到指定的存儲設備。當數據庫運行在歸檔模式下,歸檔進程負責在日誌切換後將已經寫滿的重作日誌文件複製到歸檔目標.
8. LCKn進程
是在具備並行服務器選件環境下使用,可多至10個進程(LCK0,LCK1……,LCK9),用於實例間的封鎖。
9. MMAN 進程
內存管理,若是設定了 SGA自動管理,MMAN用來協調SGA內各組件的大小設置和大小調整。
10. MMON 進程
管理性監視器(Manageability Monitor),MMON主要用於AWR,ADDM。MMON會從SGA將統計結果寫到系統表中。
MMON: The Manageability Monitor (MMON) process was introduced in 10g and is associated with the Automatic Workload Repository new features used for automatic problem detection and self-tuning. MMON writes out the required statistics for AWR on a scheduled basis.
將內存數據塊寫入數據文件實在是一個至關複雜的過程,在這個過程當中,首先要保證安全。所謂安全,就是在寫的過程當中,一旦發生實例崩潰,要有一套完整的機制可以保證用戶已經提交的數據不會丟失;其次,在保證安全的基礎上,要儘量的提升效率。衆所周知,I/O操做是最昂貴的操做,因此應該儘量的將髒數據塊收集到必定程度之後,再批量寫入磁盤中。
直觀上最簡單的解決方法就是,每當用戶提交的時候就將所改變的內存數據塊交給DBWR,由其寫入數據文件。這樣的話,必定可以保證提交的數據不會丟失。可是這種方式效率最爲低下,在高併發環境中,必定會引發I/O方面的爭用。oracle固然不會採用這種沒有擴展性的方式。oracle引入了CKPT和LGWR這兩個後臺進程,這兩個進程與DBWR進程互相合做,提供了既安全又高效的寫髒數據塊的解決方法。
用戶進程每次修改內存數據塊時,都會在日誌緩衝區(redo buffer)中構造一個相應的重作條目(redo entry),該重作條目描述了被修改的數據塊在修改以前和修改以後的值。而LGWR進程則負責將這些重作條目寫入聯機日誌文件。只要重作條目進入了聯機日誌文件,那麼數據的安全就有保障了,不然這些數據都是有安全隱患的。LGWR是一個必須和前臺用戶進程通訊的進程。LGWR承擔了維護系統數據完整性的任務,它保證了數據在任何狀況下都不會丟失。
LGWR將重作條目寫入聯機日誌文件的狀況分兩種:後臺寫(background write)和同步寫(sync write)。
觸發後臺寫的條件有四個:
1)每隔三秒鐘,LGWR啓動一次;
2)在DBWR啓動時,若是發現髒數據塊所對應的重作條目尚未寫入聯機日誌文件,則DBWR觸發LGWR進程並等待LRWR寫完之後纔會繼續;
3)重作條目的數量達到整個日誌緩衝區的1/3時,觸發LGWR;
4)重作條目的數量達到1MB時,觸發LGWR。
而觸發同步寫的條件就一個:當用戶提交(commit)時,觸發LGWR。
假如DBWR在寫髒數據塊的過程當中,忽然發生實例崩潰。咱們已經知道,用戶提交時,oracle是不必定會把提交的數據塊寫入數據文件的。那麼實例崩潰時,必然會有一些已經提交可是尚未被寫入數據文件的內存數據塊丟失了。當實例再次啓動時,oracle須要利用日誌文件中記錄的重作條目在buffer cache中從新構造出被丟失的數據塊,從而完成前滾和回滾的工做,並將丟失的數據塊找回來。因而這裏就存在一個問題,就是oracle在日誌文件中找重作條目時,到底應該找哪些重作條目?換句話說,應該在日誌文件中從哪一個起點開始日後應用重作條目?注意,這裏所指的日誌文件可能不止一個日誌文件。
由於oracle須要隨時預防可能的實例崩潰現象,因此oracle在數據庫的 正常運行過程當中,會不斷的定位這個起點,以便在不可預期的實例崩潰中可以最有效的保護並恢復數據。同時,這個起點的選擇很是有講究。首先,這個起點不能太 靠前,太靠前意味着要處理不少的重作條目,這樣會致使實例再次啓動時所進行的恢復的時間太長;其次,這個起點也不能太靠後,太靠後說明只有不多的髒數據塊 沒有被寫入數據文件,也就是說前面已經有不少髒數據塊被寫入了數據文件,那也就意味着只有在DBWR啓動的很頻繁的狀況下,才能使得buffer cache中所殘留的髒數據塊的數量不多。但很明顯,DBWR啓動的越頻繁,那麼所佔用的寫數據文件的I/O就越嚴重,那麼留給其餘操做(好比讀取buffer cache中不存在的數據塊等)的I/O資源就越少。這顯然也是不合理的。
從這裏也能夠看出,這個起點實際上說明了,在日誌文件中位於這個起點以前的重作條目所對應的在buffer cache中 的髒數據塊已經被寫入了數據文件,從而在實例崩潰之後的恢復中不須要去考慮。而這個起點之後的重作條目所對應的髒數據塊實際尚未被寫入數據文件,若是在 實例崩潰之後的恢復中,須要從這個起點開始日後,依次取出日誌文件中的重作條目進行恢復。考慮到目前的內存容量愈來愈大,buffer cache也愈來愈大,buffer cache中包含幾百萬個內存數據塊也是很正常的現象的前提下,如何才能最有效的來定位這個起點呢?
爲了可以最佳的肯定這個起點,oracle引入了名爲CKPT的後臺進程,一般也叫做檢查點進程(checkpoint process)。這個進程與DBWR共同合做,從而肯定這個起點。同時,這個起點也有一個專門的名字,叫作檢查點位置(checkpoint position)。
oracle爲了在檢查點的算法上更加的具備可擴展性(也就是爲了可以在巨大的buffer cache下依然有效工做),引入了檢查點隊列(checkpoint queue),該隊列上串起來的都是髒數據塊所對應的buffer header。
DBWR每次寫髒數據塊時,也是從檢查點隊列上掃描髒數據塊,並將這些髒數據塊實際寫入數據文件的。當寫完之後,DBWR會將這些已經寫入數據文件的髒數據塊從檢查點隊列上摘下來。這樣即使是在巨大的buffer cache下工做,CKPT也可以快速的肯定哪些髒數據塊已經被寫入了數據文件,而哪些尚未寫入數據文件,顯然,只要在檢查點隊列上的數據塊都是尚未寫入數據文件的髒數據塊。
爲了更加有效的處理單實例和多實例(RAC)環境下的表空間的檢查點處理,好比將表空間設置爲離線狀態或者爲熱備份狀態等,oracle還專門引入了文件隊列(file queue)。文件隊列的原理與檢查點隊列是同樣的,只不過每一個數據文件會有一個文件隊列,該數據文件所對應的髒數據塊會被串在同一個文件隊列上;同時爲了可以儘可能減小實例崩潰後恢復的時間,oracle還引入了增量檢查點(incremental checkpoint),從而增長了檢查點啓動的次數。
若是每次檢查點啓動的間隔時間過長的話,再加上內存很大,可能會使得恢復的時間過長。由於前一次檢查點啓動之後,標識出了這個起點。而後在第二次檢查點啓動的過程當中,DBWR可能已經將不少髒數據塊已經寫入了數據文件,而假如在第二次檢查點啓動以前發生實例崩潰,致使在日誌文件中,所標識的起點仍然是上一次檢查點啓動時所標識的,致使oracle不知道這個起點之後的不少重作條目所對應的髒數據塊實際上已經寫入了數據文件,從而使得oracle在實例恢復時再次重複的處理一遍,效率低下,浪費時間。
上面說到了有關CKPT的兩個重要的概念:檢查點隊列(包括文件隊列)和增量檢查點。
檢查點隊列在咱們上面轉儲出來的buffer header裏能夠看到,就是相似ckptq: [65abceb4,63bec66c]和fileq: [65abcfbc,63becd10]的結構,記錄的一樣都是指向前一個buffer header和指向後一個buffer header的指針。這個隊列上面掛的也是髒數據塊對應的buffer header鏈表,可是它與LRUW鏈表不一樣。檢查點隊列上的buffer header是按照數據塊第一次被修改的時間的前後順序來排列的。越早修改的數據塊的buffer header排在越前面,同時若是一個數據塊被修改了屢次的話,在該鏈表上也只出現一次。並且,檢查點隊列上的buffer header還記錄了髒數據塊在第一次被修改時,所對應的重作條目在重作日誌文件中的地址,也就是RBA(Redo Block Address)。一樣在轉儲出來的buffer header中能夠看到相似LRBA: [0xe9.229.0]的結構,這就是RBA,L表示Low,也就是第一次被修改的時候的RBA。可是注意,在檢查點隊列上的buffer header,並不表示必定會有一個對應的RBA,好比控制文件重作(controlfile redo)就不會有相應的RBA。對於沒有對應RBA的buffer header來講,在檢查點隊列上始終處於最尾端,其優先級永遠比有RBA的髒數據塊的buffer header要低。8i之前,每一個working set都有一個檢查點隊列以及多個文件隊列(由於一個數據文件對應一個文件隊列);而從8i開始,每一個working set都有兩個檢查點隊列,每一個檢查點都會由checkpoint queue latch來保護。
增量檢查點是從8i開始出現的,是相對於8i以前的徹底檢查點(complete checkpoint)而言的。徹底檢查點啓動時,會標識出buffer cache中全部的髒數據塊,而後啓動DBWR進程將這些髒數據塊寫入數據文件。8i以前,日誌切換的時候會觸發徹底檢查點。
而到了8i及之後,徹底檢查點只有在兩種狀況下才會被觸發:
1)發出命令:alter system checkpoint;
2)除了shutdown abort之外的正常關閉數據庫。
注意,這個時候,日誌切換不會觸發徹底檢查點,而是觸發增量檢查點。8i所引入的增量檢查點每隔三秒鐘或發生日誌切換時啓動。它啓動時只作一件事情:找出當前檢查點隊列上的第一個buffer header,並將該buffer header中所記錄的LRBA(這個LRBA也就是checkpoint position了)記錄到控制文件中去。若是是由日誌切換所引發的增量檢查點,則還會將checkpoint position記錄到每一個數據文件頭中。也就是說,若是這個時候發生實例崩潰,oracle在下次啓動時,就會到控制文件中找到這個checkpoint position做爲在日誌文件中的起點,而後從這個起點開始向後,依次取出每一個重作條目進行處理。
上面所描述的概念,用一句話來歸納,其實就是DBWR負責寫檢查點隊列上的髒數據塊,而CKPT負責記錄當前檢查點隊列的第一個數據塊所對應的的重作條目在日誌文件中的地址。從這個意義上說,檢查點隊列比LRUW還要重要,LRUW主要就是區分出哪些數據塊是髒的,不能夠被重用的。而到底應該寫哪些髒數據塊,寫多少髒數據塊,則仍是要到檢查點隊列上才能肯定的。
咱們用一個簡單的例子來描述這個過程。假設系統中發生了一系列的事務,致使日誌文件以下所示:
事務號 數據文件號 block號 行號 列 值 RBA
T1 8 25 10 1 10 101
T1 7 623 12 2 a 102
T3 8 80 56 3 b 103
T3 9 98 124 7 e 104
T5 7 623 13 3 abc 105
Commit SCN# timestamp 106
T123 8 876 322 10 89 107
這時,對應的檢查點隊列則相似以下圖六所示。咱們能夠看到,T1事務最早發生,因此位於檢查點
圖六
隊列的首端,而事務T123最後發生,因此位於靠近尾端的地方。同時,能夠看到事務T1和T5都更新了7號數據文件的623號數據塊。而在檢查點隊列上只會記錄該數據塊的第一次被更新時的RBA,也就是事務T1對應的RBA102,而事務T5對應的RBA105並不會被記錄。由於根本就不須要在檢查點隊列上記錄。當DBWR寫數據塊的時候,在寫RBA102時,天然就把RBA105所修改的內容寫入數據文件了。日誌文件中所記錄的提交標記也不會體如今檢查點隊列上,由於提交自己只是一個標記而已,不會涉及到修改數據塊。
這時,假設發生三秒鐘超時,因而增量檢查點啓動。增量檢查點會將檢查點隊列的第一個髒數據塊所對應的RBA記錄到控制文件中去。在這裏,也就是RBA101會做爲checkpointposition記錄到控制文件中。
而後,DBWR後臺進程被某種條件觸發而啓動。DBWR根據一系列參數及規則,計算出應該寫的髒數據塊的數量,從而將RBA101到RBA107之間的這5個髒數據塊寫入數據文件,並在寫完之後將這5個髒數據塊從檢查點隊列上摘除,而留下了4個髒數據塊在檢查點隊列上。若是在寫這5個髒數據塊的過程當中發生實例崩潰,則下次實例啓動時,oracle會從RBA101開始應用日誌文件中的重作條目。
圖七
而在9i之後,在DBWR寫完這5個髒數據塊之後,還會在日誌文件中記錄所寫的髒數據塊的塊號。以下圖所示。這主要是爲了在恢復時加快恢復的速度。
圖八
這時,又發生三秒鐘超時,因而增量檢查點啓動。這時它發現checkpointposition爲RBA109,因而將RBA109寫入控制文件。若是接着發生實例崩潰,則oracle在下次啓動時,就會從RBA109開始應用日誌。