一 . 進程概述
先來看一下 Oracle 11g 的架構(gòu)圖。 看起來比較模糊,我已經(jīng)上傳到了 csdn 的下載。 是個 pdf 文件, 2m 多。 那個看起來比較清楚。 也對每個進程做了解釋。
下載地址: Oracle 11g 架構(gòu)圖 from Oracle University
http://download.csdn.net/source/2346700
進程是操作系統(tǒng)中的一種機制,它可執(zhí)行一系列的操作步。在有些操作系統(tǒng)中使用作業(yè)
(JOB)
或任務(wù)
(TASK)
的術(shù)語。一個進程通常有它自己的專用存儲區(qū)。
ORACLE
進程的體系結(jié)構(gòu)設(shè)計使性能最大。
ORACLE
實例有兩種類型:
單進程實例
和
多進程實例
。
單進程
ORACLE
(又稱單用
ORACLE
)是一種數(shù)據(jù)庫系統(tǒng),一個進程執(zhí)行全部
ORACLE
代碼。由于
ORACLE
部分和客戶應(yīng)用程序不能分別以進程執(zhí)行,所以
ORACLE
的代碼和用戶的數(shù)據(jù)庫應(yīng)用是單個進程執(zhí)行。
在單進程環(huán)境下的
ORACLE
實例,僅允許一個用戶可存取。例如在
MS-DOS
上運行
ORACLE
。
多進程
ORACLE
實例
(又稱多用戶
ORACLE
)使用多個進程來執(zhí)行
ORACLE
的不同部分
,對于每一個連接的用戶都有一個進程。
在多進程系統(tǒng)中,進程分為兩類:
用戶進程
和
ORACLE
進程
。當一用戶運行一應(yīng)用程序,如
PRO*C
程序或一個
ORACLE
工具(如
SQL*PLUS
),為用戶運行的應(yīng)用建立一個用戶進程。
ORACLE 進程又分為兩類 :服務(wù)器進程 和 后臺進程 。
服務(wù)器進程用于處理連接到該實例的用戶進程的請求
。當應(yīng)用和
ORACELE
是在同一臺機器上運行,而不再通過網(wǎng)絡(luò),一般將用戶進程和它相應(yīng)的服務(wù)器進程組合成單個的進程,可降低系統(tǒng)開銷。然而,當應(yīng)用和
ORACLE
運行在不同的機器上時,用戶進程經(jīng)過一個分離服務(wù)器進程與
ORACLE
通信。它可執(zhí)行下列任務(wù):
1)
對應(yīng)用所發(fā)出的
SQL
語句進行語法分析和執(zhí)行。
2)
從磁盤(數(shù)據(jù)文件)中讀入必要的數(shù)據(jù)塊到
SGA
的共享數(shù)據(jù)庫緩沖區(qū)(該塊不在緩沖區(qū)時)。
3)
將結(jié)果返回給應(yīng)用程序處理。
系統(tǒng)為了使性能最好和協(xié)調(diào)多個用戶,在多進程系統(tǒng)中使用一些附加進程,
稱為后臺進程
。在許多操作系統(tǒng)中,
后臺進程是在實例啟動時自動地建立
。一個
ORACLE
實例可以有許多后臺進程,但它們不是一直存在。
后臺進程有:
DBWR(Database Write) :
數(shù)據(jù)庫寫入程序
LGWR(Log Write) :
日志寫入程序
CKPT(Checkpoint) :
檢查點
SMON (System Monitor):
系統(tǒng)監(jiān)控
PMON(Process Monitor) :
進程監(jiān)控
ARCH(Archive) :
歸檔
RECO :
恢復(fù)
LCKn :
封鎖;
這是
RAC
環(huán)境啟動時
,
各個進程的啟動順序:
PMON started with pid=2, OS id=18042
DIAG started with pid=3, OS id=18044
PSP0 started with pid=4, OS id=18051
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 數(shù)據(jù)庫的不同部分交互。 其中 SMON 、 PMON 、 DBWn 、 CKPT 、 LGWR 是五個必須的 ORACLE 后臺進程。
二 . 進程詳細說明
1. DBWR 進程
該進程執(zhí)行將緩沖區(qū)寫入數(shù)據(jù)文件,是負責(zé)緩沖存儲區(qū)管理的一個
ORACLE
后臺進程。當緩沖區(qū)中的一緩沖區(qū)被修改,它被標志為
“
弄臟
”
,
DBWR
的主要任務(wù)是將
“
弄臟
”
的緩沖區(qū)寫入磁盤,使緩沖區(qū)保持
“
干凈
”
。由于緩沖存儲區(qū)的緩沖區(qū)填入數(shù)據(jù)庫或被用戶進程弄臟,未用的緩沖區(qū)的數(shù)目減少。當未用的緩沖區(qū)下降到很少,以致用戶進程要從磁盤讀入塊到內(nèi)存存儲區(qū)時無法找到未用的緩沖區(qū)時,
DBWR
將管理緩沖存儲區(qū),使用戶進程總可得到未用的緩沖區(qū)。
ORACLE
采用
LRU
(
LEAST RECENTLY USED
)算法(最近最少使用算法)保持內(nèi)存中的數(shù)據(jù)塊是最近使用的,使
I/O
最小。
觸發(fā)
DBWR
進程的條件有:
1.
DBWR
超時,大約
3
秒
2.
系統(tǒng)中沒有多余的空緩沖區(qū)來存放數(shù)據(jù)
3.
CKPT
進程觸發(fā)
DBWR
在有些平臺上,一個實例可有多個
DBWR
。在這樣的實例中,一些塊可寫入一磁盤,另一些塊可寫入其它磁盤。
2. LGWR 進程
該進程將日志緩沖區(qū)寫入磁盤上的一個日志文件,它是負責(zé)管理日志緩沖區(qū)的一個 ORACLE 后臺進程。
觸發(fā)
LGWR
進程的條件有:
1.
用戶提交
2.
有
1/3
重做日志緩沖區(qū)未被寫入磁盤
3.
有大于
1M
的重做日志緩沖區(qū)未被寫入磁盤
4. 3
秒超時
5. DBWR
需要寫入的數(shù)據(jù)的
SCN
大于
LGWR
記錄的
SCN
,
DBWR
觸發(fā)
LGWR
寫入。
日志緩沖區(qū)
是一個循環(huán)緩沖區(qū)。當
LGWR
將日志緩沖區(qū)的日志項寫入日志文件后,服務(wù)器進程可將新的日志項寫入到該日志緩沖區(qū)。
LGWR
通常寫得很快,可確保日志緩沖區(qū)總有空間可寫入新的日志項。
注意:有時候當需要更多的日志緩沖區(qū)時,
LWGR
在一個事務(wù)提交前就將日志項寫出
,而這些日志項僅當在以后事務(wù)提交后才永久化。
ORACLE
使用快速提交機制,當用戶發(fā)出
COMMIT
語句時,一個
COMMIT
記錄立即放入日志緩沖區(qū),但相應(yīng)的數(shù)據(jù)緩沖區(qū)改變是被延遲,直到在更有效時才將它們寫入數(shù)據(jù)文件
。當一事務(wù)提交時,被賦給一個系統(tǒng)修改號(
SCN
),它同事務(wù)日志項一起記錄在日志中。由于
SCN
記錄在日志中,以致在并行服務(wù)器選項配置情況下,恢復(fù)操作可以同步。
3. CKPT
進程
該進程在檢查點出現(xiàn)時,對全部數(shù)據(jù)文件的標題進行修改,指示該檢查點。負責(zé)在每當緩沖區(qū)高速緩存中的更改永久地記錄在數(shù)據(jù)庫中時 , 更新控制文件和數(shù)據(jù)文件中的數(shù)據(jù)庫狀態(tài)信息。
RedoLog Checkpoint 和 SCN 關(guān)系
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 數(shù)據(jù)庫至關(guān)重要的一個后臺進程 , 該進程實例啟動時執(zhí)行實例恢復(fù),還負責(zé)清理不再使用的臨時段 , 是一種用于庫的 “ 垃圾收集者 ” 。在具有并行服務(wù)器選項的環(huán)境下, SMON 對有故障 CPU 或?qū)嵗M行實例恢復(fù)。 SMON 進程有規(guī)律地被呼醒,檢查是否需要,或者其它進程發(fā)現(xiàn)需要時可以被調(diào)用。
它做的工作包括如下 7 件:
(
1
)清理臨時表空間:
伴隨這
“
真正
”
的臨時表空間的出現(xiàn),清理臨時表空間的雜事已經(jīng)減輕了,但它還沒完全消失。例如,當建立一個索引,在創(chuàng)建期間分配給索引的擴展區(qū)被標志為
TEMPORARY
。如果
Create Index
會話因某些原因異常中斷,
SMON
負責(zé)清理他們。其他操作創(chuàng)建的臨時擴展區(qū),
SMON
同樣會負責(zé)。
(
2
)
接合空閑空間:
如果你正使用數(shù)據(jù)字典管理表空間,
SMON
負責(zé)把那些在表空間中空閑的并且互相是鄰近的
extent
接合成一個較大的空閑擴展區(qū)。這發(fā)生僅在帶有默認的
pctincrease
設(shè)置為非零的存儲子句的字典管理表空間。
(
3
)
把對于不可用文件的事務(wù)恢復(fù)成活動狀態(tài):
它的角色類似在庫啟動期間。這時,因為文件不能用于恢復(fù),
SMON
恢復(fù)在實例
/
崩潰恢復(fù)期間被跳過的故障事務(wù)。例如,文件可能已經(jīng)在不可用或沒裝載的磁盤上。當文件變可用了,
SMON
將恢復(fù)它。
(
4
)執(zhí)行一個
RAC
中故障節(jié)點的實例恢復(fù):
在一個
oracle RAC
配置中,當群集中的一個庫實例失敗(例如,實例正執(zhí)行的機器故障了),一些群集中的其他節(jié)點將開啟故障的實例的重做日志文件,為故障實例執(zhí)行所有數(shù)據(jù)的恢復(fù)。
(
5
)清理
OBJ$
:
OBJ$
是一個包含庫中幾乎每一個對象(表,索引,觸發(fā)器,視圖等等)的記錄的行級數(shù)據(jù)字典表。許多次,這兒存在的記錄代表已刪對象,或代表不在這兒的對象,在
oracle
的信賴機制中被使用。
SMON
是刪除這些不在被需要的行的進程。
(
6
)收縮回滾段:
SMON
將執(zhí)行回滾段的自動收縮到它的
optimal
尺寸,如果它被設(shè)置。
(
7
)
“
脫機
”
回滾段:
對于
DBA
來,讓一個有
active
事務(wù)的回滾段,脫機或不可用,這事是可能的。
Active
事務(wù)正使用這脫機回滾段是可能的。在這情況下,回滾不是真正的脫機;它被標志為
“
懸掛
offline”
。在后臺進程中,
SMON
將周期性盡力讓它真正脫機,直到成功。
SMON 做許多其他事情,譬如存在 DBA_TAB_MONITORING 視圖中的監(jiān)控統(tǒng)計數(shù)據(jù)的洗刷, 在 SMON_SCN_TIME 表中發(fā)現(xiàn)的時間戳定位信息的 SCN 的洗刷 ,等等。 SMON 在期間能消耗很多 CPU ,這應(yīng)該被認為是正常的。 SMON 周期性的蘇醒(或被其他后臺進程叫醒)來執(zhí)行這些管家的家庭雜事。
5. PMON 進程
用于恢復(fù)失敗的數(shù)據(jù)庫用戶的強制性進程,它先獲取失敗用戶的標識,釋放該用戶占有的所有數(shù)據(jù)庫資源。 PMON 有規(guī)律地被呼醒,檢查是否需要,或者其它進程發(fā)現(xiàn)需要時可以被調(diào)用。
PMON 進程負責(zé)在反常中斷的連接之后的清理工作。 例如,如果因某些原因?qū)S梅?wù) “ 故障 ” 或被 kill 掉, PMON 就是負責(zé)處理(恢復(fù)或回滾工作)和釋放你的資源。 PMON 將發(fā)出未提交工作的回滾,釋放鎖,和釋放分配給故障進程的 SGA 資源 。除了在異常中斷之后的清理外, PMON 監(jiān)控其他 oracle 后臺進程,如果有必要(和有可能)重新啟動他們。如果共享服務(wù)或一個分配器故障(崩潰), PMON 將插手并且重啟另一個(在清理故障進程之后)。
PMON 將觀察所有 Oracle 進程,只要合適或重啟他們或中止進程。 例如,在數(shù)據(jù)庫日志寫進程事件中, LGWR 故障,實例故障。這是一個嚴重的錯誤,最安全的處理方法就是去立即終止實例,讓正常的恢復(fù)處理數(shù)據(jù)。
PMON 為實例做的另一件事是去使用 Oracle TNS 監(jiān)聽器登記。 當一個實例開啟的時候, PMON 進程投出眾所周知的端口地址,除非指向其他,來看是否監(jiān)聽器正在開和運行著。眾所周知 / 默認端口是使用 1521 。
現(xiàn)在,如果監(jiān)聽器在一些不同端口開啟會發(fā)生什么?這種情況,機制是相同的,除了監(jiān)聽器地址需要被 LOCAL_LISTENER 參數(shù)明確指定。如果監(jiān)聽器運行在庫實例開啟的時候, PMON 和監(jiān)聽器通訊,傳到它相關(guān)參數(shù),譬如服務(wù)器名和實例的負載度量。如果監(jiān)聽器沒被開啟, PMON 將周期性的試著和它聯(lián)系來登記自己。
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 進程
負責(zé)在分布式數(shù)據(jù)庫環(huán)境中自動恢復(fù)那些失敗的分布式事務(wù) , 保證分布式事務(wù)的一致性 , 在分布式事務(wù)中 , 要么同時 commit, 要么同時 rollback;
7. ARCH 進程
該進程將已填滿的在線日志文件拷貝到指定的存儲設(shè)備。當數(shù)據(jù)庫運行在歸檔模式下,歸檔進程負責(zé)在日志切換后將已經(jīng)寫滿的重做日志文件復(fù)制到歸檔目標 .
8. LCKn
進程
是在具有并行服務(wù)器選件環(huán)境下使用,可多至 10 個進程( LCK0 , LCK1…… , LCK9 ),用于實例間的封鎖。
9. MMAN 進程
內(nèi)存管理 , 如果設(shè)定了 SGA 自動管理, MMAN 用來協(xié)調(diào) SGA 內(nèi)各組件的大小設(shè)置和大小調(diào)整。
10. MMON 進程
管理性監(jiān)視器( Manageability Monitor ), MMON 主要用于 AWR , ADDM 。 MMON 會從 SGA 將統(tǒng)計結(jié)果寫到系統(tǒng)表中。
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.
三 . DBWR 、 CKPT 、 LGWR 進程之間的關(guān)系
將內(nèi)存數(shù)據(jù)塊寫入數(shù)據(jù)文件實在是一個相當復(fù)雜的過程,在這個過程中,首先要保證安全。所謂安全,就是在寫的過程中,一旦發(fā)生實例崩潰,要有一套完整的機制能夠保證用戶已經(jīng)提交的數(shù)據(jù)不會丟失;其次,在保證安全的基礎(chǔ)上,要盡可能的提高效率。眾所周知, I/O 操作是最昂貴的操作,所以應(yīng)該盡可能的將臟數(shù)據(jù)塊收集到一定程度以后,再批量寫入磁盤中。
直觀上最簡單的解決方法就是,每當用戶提交的時候就將所改變的內(nèi)存數(shù)據(jù)塊交給 DBWR ,由其寫入數(shù)據(jù)文件。這樣的話,一定能夠保證提交的數(shù)據(jù)不會丟失。但是這種方式效率最為低下,在高并發(fā)環(huán)境中,一定會引起 I/O 方面的爭用。 oracle 當然不會采用這種沒有擴展性的方式。 oracle 引入了 CKPT 和 LGWR 這兩個后臺進程,這兩個進程與 DBWR 進程互相合作,提供了既安全又高效的寫臟數(shù)據(jù)塊的解決方法。
用戶進程每次修改內(nèi)存數(shù)據(jù)塊時,都會在日志緩沖區(qū)( redo buffer )中構(gòu)造一個相應(yīng)的重做條目( redo entry ),該重做條目描述了被修改的數(shù)據(jù)塊在修改之前和修改之后的值。而 LGWR 進程則負責(zé)將這些重做條目寫入聯(lián)機日志文件。只要重做條目進入了聯(lián)機日志文件,那么數(shù)據(jù)的安全就有保障了,否則這些數(shù)據(jù)都是有安全隱患的。 LGWR 是一個必須和前臺用戶進程通信的進程。 LGWR 承擔了維護系統(tǒng)數(shù)據(jù)完整性的任務(wù),它保證了數(shù)據(jù)在任何情況下都不會丟失。
LGWR 將重做條目寫入聯(lián)機日志文件的情況分兩種: 后臺寫( background write ) 和 同步寫( sync write ) 。
觸發(fā)后臺寫的條件 有四個:
1) 每隔三秒鐘, LGWR 啟動一次;
2) 在 DBWR 啟動時,如果發(fā)現(xiàn)臟數(shù)據(jù)塊所對應(yīng)的重做條目還沒有寫入聯(lián)機日志文件,則 DBWR 觸發(fā) LGWR 進程并等待 LRWR 寫完以后才會繼續(xù);
3) 重做條目的數(shù)量達到整個日志緩沖區(qū)的 1/3 時,觸發(fā) LGWR ;
4) 重做條目的數(shù)量達到 1MB 時,觸發(fā) LGWR 。
而 觸發(fā)同步寫的條件 就一個:當用戶提交( commit )時,觸發(fā) LGWR 。
假如 DBWR 在寫臟數(shù)據(jù)塊的過程中,突然發(fā)生實例崩潰。我們已經(jīng)知道,用戶提交時, oracle 是不一定會把提交的數(shù)據(jù)塊寫入數(shù)據(jù)文件的。那么實例崩潰時,必然會有一些已經(jīng)提交但是還沒有被寫入數(shù)據(jù)文件的內(nèi)存數(shù)據(jù)塊丟失了。當實例再次啟動時, oracle 需要利用日志文件中記錄的重做條目在 buffer cache 中重新構(gòu)造出被丟失的數(shù)據(jù)塊,從而完成前滾和回滾的工作,并將丟失的數(shù)據(jù)塊找回來。于是這里就存在一個問題,就是 oracle 在日志文件中找重做條目時,到底應(yīng)該找哪些重做條目?換句話說,應(yīng)該在日志文件中從哪個起點開始往后應(yīng)用重做條目?注意,這里所指的日志文件可能不止一個日志文件。
因為 oracle 需要隨時預(yù)防可能的實例崩潰現(xiàn)象,所以 oracle 在 數(shù)據(jù)庫 的正常運行過程中,會不斷的定位這個起點,以便在不可預(yù)期的實例崩潰中能夠最有效的保護并恢復(fù)數(shù)據(jù)。同時,這個起點的選擇非常有講究。首先,這個起點不能太靠前,太靠前意味著要處理很多的重做條目,這樣會導(dǎo)致實例再次啟動時所進行的恢復(fù)的時間太長;其次,這個起點也不能太靠后,太靠后說明只有很少的臟數(shù)據(jù)塊沒有被寫入數(shù)據(jù)文件,也就是說前面已經(jīng)有很多臟數(shù)據(jù)塊被寫入了數(shù)據(jù)文件,那也就意味著只有在 DBWR 啟動的很頻繁的情況下,才能使得 buffer cache 中所殘留的臟數(shù)據(jù)塊的數(shù)量很少。但很明顯, DBWR 啟動的越頻繁,那么所占用的寫數(shù)據(jù)文件的 I/O 就越嚴重,那么留給其他操作(比如讀取 buffer cache 中不存在的數(shù)據(jù)塊等)的 I/O 資源就越少。這顯然也是不合理的。
從這里也可以看出,這個起點實際上說明了,在日志文件中位于這個起點之前的重做條目所對應(yīng)的在 buffer cache 中的臟數(shù)據(jù)塊已經(jīng)被寫入了數(shù)據(jù)文件,從而在實例崩潰以后的恢復(fù)中不需要去考慮。而這個起點以后的重做條目所對應(yīng)的臟數(shù)據(jù)塊實際還沒有被寫入數(shù)據(jù)文件,如果在實例崩潰以后的恢復(fù)中,需要從這個起點開始往后,依次取出日志文件中的重做條目進行恢復(fù)。考慮到目前的內(nèi)存容量越來越大, buffer cache 也越來越大, buffer cache 中包含幾百萬個內(nèi)存數(shù)據(jù)塊也是很正常的現(xiàn)象的前提下,如何才能最有效的來定位這個起點呢?
為了能夠最佳的確定這個起點, oracle 引入了名為 CKPT 的后臺進程,通常也叫作 檢查點進程( checkpoint process ) 。這個進程與 DBWR 共同合作,從而確定這個起點。同時,這個起點也有一個專門的名字,叫做 檢查點位置( checkpoint position ) 。
oracle 為了在檢查點的算法上更加的具有可擴展性(也就是為了能夠在巨大的 buffer cache 下依然有效工作),引入了 檢查點隊列( checkpoint queue ) ,該隊列上串起來的都是臟數(shù)據(jù)塊所對應(yīng)的 buffer header 。
DBWR 每次寫臟數(shù)據(jù)塊時,也是從檢查點隊列上掃描臟數(shù)據(jù)塊,并將這些臟數(shù)據(jù)塊實際寫入數(shù)據(jù)文件的。當寫完以后, DBWR 會將這些已經(jīng)寫入數(shù)據(jù)文件的臟數(shù)據(jù)塊從檢查點隊列上摘下來。這樣即便是在巨大的 buffer cache 下工作, CKPT 也能夠快速的確定哪些臟數(shù)據(jù)塊已經(jīng)被寫入了數(shù)據(jù)文件,而哪些還沒有寫入數(shù)據(jù)文件,顯然,只要在檢查點隊列上的數(shù)據(jù)塊都是還沒有寫入數(shù)據(jù)文件的臟數(shù)據(jù)塊。
為了更加有效的處理單實例和多實例( RAC )環(huán)境下的表空間的檢查點處理,比如將表空間設(shè)置為離線狀態(tài)或者為熱備份狀態(tài)等, oracle 還專門引入了 文件隊列( file queue ) 。文件隊列的原理與檢查點隊列是一樣的,只不過每個數(shù)據(jù)文件會有一個文件隊列,該數(shù)據(jù)文件所對應(yīng)的臟數(shù)據(jù)塊會被串在同一個文件隊列上;同時為了能夠盡量減少實例崩潰后恢復(fù)的時間, oracle 還引入了 增量檢查點( incremental checkpoint ) ,從而增加了檢查點啟動的次數(shù)。
如果每次檢查點啟動的間隔時間過長的話,再加上內(nèi)存很大,可能會使得恢復(fù)的時間過長。因為前一次檢查點啟動以后,標識出了這個起點。然后在第二次檢查點啟動的過程中, DBWR 可能已經(jīng)將很多臟數(shù)據(jù)塊已經(jīng)寫入了數(shù)據(jù)文件,而假如在第二次檢查點啟動之前發(fā)生實例崩潰,導(dǎo)致在日志文件中,所標識的起點仍然是上一次檢查點啟動時所標識的,導(dǎo)致 oracle 不知道這個起點以后的很多重做條目所對應(yīng)的臟數(shù)據(jù)塊實際上已經(jīng)寫入了數(shù)據(jù)文件,從而使得 oracle 在實例恢復(fù)時再次重復(fù)的處理一遍,效率低下,浪費時間。
上面說到了 有關(guān) CKPT 的兩個重要的概念:檢查點隊列(包括文件隊列)和增量檢查點 。
檢查點隊列 在我們上面轉(zhuǎn)儲出來的 buffer header 里可以看到,就是類似 ckptq: [65abceb4,63bec66c] 和 fileq: [65abcfbc,63becd10] 的結(jié)構(gòu),記錄的同樣都是指向前一個 buffer header 和指向后一個 buffer header 的指針。這個隊列上面掛的也是臟數(shù)據(jù)塊對應(yīng)的 buffer header 鏈表,但是它與 LRUW 鏈表不同。 檢查點隊列上的 buffer header 是按照數(shù)據(jù)塊第一次被修改的時間的先后順序來排列的 。越早修改的數(shù)據(jù)塊的 buffer header 排在越前面,同時如果一個數(shù)據(jù)塊被修改了多次的話,在該鏈表上也只出現(xiàn)一次。而且,檢查點隊列上的 buffer header 還記錄了臟數(shù)據(jù)塊在第一次被修改時,所對應(yīng)的重做條目在重做日志文件中的地址,也就是 RBA ( Redo Block Address )。同樣在轉(zhuǎn)儲出來的 buffer header 中可以看到類似 LRBA: [0xe9.229.0] 的結(jié)構(gòu), 這就是 RBA , L 表示 Low ,也就是第一次被修改的時候的 RBA 。但是注意,在檢查點隊列上的 buffer header ,并不表示一定會有一個對應(yīng)的 RBA ,比如控制文件重做( controlfile redo )就不會有相應(yīng)的 RBA 。對于沒有對應(yīng) RBA 的 buffer header 來說,在檢查點隊列上始終處于最尾端,其優(yōu)先級永遠比有 RBA 的臟數(shù)據(jù)塊的 buffer header 要低。 8i 以前,每個 working set 都有一個檢查點隊列以及多個文件隊列(因為一個數(shù)據(jù)文件對應(yīng)一個文件隊列);而從 8i 開始,每個 working set 都有兩個檢查點隊列,每個檢查點都會由 checkpoint queue latch 來保護。
增量檢查點 是從 8i 開始出現(xiàn)的,是相對于 8i 之前的完全檢查點( complete checkpoint )而言的。完全檢查點啟動時,會標識出 buffer cache 中所有的臟數(shù)據(jù)塊,然后啟動 DBWR 進程將這些臟數(shù)據(jù)塊寫入數(shù)據(jù)文件。 8i 之前,日志切換的時候會觸發(fā)完全檢查點。
而到了 8i 及以后,完全檢查點只有在兩種情況下才會被觸發(fā):
1) 發(fā)出命令: alter system checkpoint ;
2) 除了 shutdown abort 以外的正常關(guān)閉數(shù)據(jù)庫。
注意, 這個時候,日志切換不會觸發(fā)完全檢查點,而是觸發(fā)增量檢查點。 8i 所引入的增量檢查點每隔三秒鐘或發(fā)生日志切換時啟動。 它啟動時只做一件事情:找出當前檢查點隊列上的第一個 buffer header ,并將該 buffer header 中所記錄的 LRBA (這個 LRBA 也就是 checkpoint position 了)記錄到控制文件中去 。如果是由日志切換所引起的增量檢查點,則還會將 checkpoint position 記錄到每個數(shù)據(jù)文件頭中。也就是說,如果這個時候發(fā)生實例崩潰, oracle 在下次啟動時,就會到控制文件中找到這個 checkpoint position 作為在日志文件中的起點,然后從這個起點開始向后,依次取出每個重做條目進行處理。
上面所描述的概念,用一句話來概括,其實就是 DBWR 負責(zé)寫檢查點隊列上的臟數(shù)據(jù)塊,而 CKPT 負責(zé)記錄當前檢查點隊列的第一個數(shù)據(jù)塊所對應(yīng)的的重做條目在日志文件中的地址。 從這個意義上說,檢查點隊列比 LRUW 還要重要, LRUW 主要就是區(qū)分出哪些數(shù)據(jù)塊是臟的,不可以被重用的。而到底應(yīng)該寫哪些臟數(shù)據(jù)塊,寫多少臟數(shù)據(jù)塊,則還是要到檢查點隊列上才能確定的。
我們用一個簡單的例子來描述這個過程。假設(shè)系統(tǒng)中發(fā)生了一系列的事務(wù),導(dǎo)致日志文件如下所示:
事務(wù)號 數(shù)據(jù)文件號 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
這時,對應(yīng)的檢查點隊列則類似如下圖六所示。我們可以看到, T1 事務(wù)最先發(fā)生,所以位于檢查點
圖六
隊列的首端,而事務(wù) T123 最后發(fā)生,所以位于靠近尾端的地方。同時,可以看到事務(wù) T1 和 T5 都更新了 7 號數(shù)據(jù)文件的 623 號數(shù)據(jù)塊。而在檢查點隊列上只會記錄該數(shù)據(jù)塊的第一次被更新時的 RBA ,也就是事務(wù) T1 對應(yīng)的 RBA102 ,而事務(wù) T5 對應(yīng)的 RBA105 并不會被記錄。因為根本就不需要在檢查點隊列上記錄。當 DBWR 寫數(shù)據(jù)塊的時候,在寫 RBA102 時,自然就把 RBA105 所修改的內(nèi)容寫入數(shù)據(jù)文件了。日志文件中所記錄的提交標記也不會體現(xiàn)在檢查點隊列上,因為提交本身只是一個標記而已,不會涉及到修改數(shù)據(jù)塊。
這時,假設(shè)發(fā)生三秒鐘超時,于是增量檢查點啟動。增量檢查點會將檢查點隊列的第一個臟數(shù)據(jù)塊所對應(yīng)的 RBA 記錄到控制文件中去。在這里,也就是 RBA101 會作為 checkpointposition 記錄到控制文件中。
然后, DBWR 后臺進程被某種條件觸發(fā)而啟動。 DBWR 根據(jù)一系列參數(shù)及規(guī)則,計算出應(yīng)該寫的臟數(shù)據(jù)塊的數(shù)量,從而將 RBA101 到 RBA107 之間的這 5 個臟數(shù)據(jù)塊寫入數(shù)據(jù)文件,并在寫完以后將這 5 個臟數(shù)據(jù)塊從檢查點隊列上摘除,而留下了 4 個臟數(shù)據(jù)塊在檢查點隊列上。如果在寫這 5 個臟數(shù)據(jù)塊的過程中發(fā)生實例崩潰,則下次實例啟動時, oracle 會從 RBA101 開始應(yīng)用日志文件中的重做條目。
圖七
而在 9i 以后,在 DBWR 寫完這 5 個臟數(shù)據(jù)塊以后,還會在日志文件中記錄所寫的臟數(shù)據(jù)塊的塊號。如下圖所示。這主要是為了在恢復(fù)時加快恢復(fù)的速度。
圖八
這時,又發(fā)生三秒鐘超時,于是增量檢查點啟動。這時它發(fā)現(xiàn) checkpointposition 為 RBA109 ,于是將 RBA109 寫入控制文件。如果接著發(fā)生實例崩潰,則 oracle 在下次啟動時,就會從 RBA109 開始應(yīng)用日志。
注:整理自網(wǎng)絡(luò)
-------------------------------------------------------------------------------------------------------
Blog : http://blog.csdn.net/tianlesoftware
Email: dvd.dba@gmail.com
DBA1 群: 62697716( 滿 ); DBA2 群: 62697977( 滿 ) DBA3 群: 62697850( 滿 )
DBA 超級群: 63306533( 滿 ); DBA4 群: 83829929 DBA5 群: 142216823
DBA6 群: 158654907 聊天 群: 40132017 聊天 2 群: 69087192
-- 加群需要在備注說明 Oracle 表空間和數(shù)據(jù)文件的關(guān)系,否則拒絕申請
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
