日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Oracle 实例崩溃恢复原理剖析 -- 检查点队列的作用与意义

發(fā)布時(shí)間:2025/3/20 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle 实例崩溃恢复原理剖析 -- 检查点队列的作用与意义 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這篇文章是參考甲骨論老相老師的教學(xué)視頻

http://v.youku.com/v_show/id_XNDAxMzI3NzI4.html

所做的學(xué)習(xí)筆記



檢查點(diǎn)隊(duì)列的內(nèi)容已經(jīng)在上一篇文章里講過:

http://blog.csdn.net/nvd11/article/details/8749393

這篇章雖然是講實(shí)例崩潰恢復(fù)的原理, 但實(shí)際上講的就是checkpoint queue的作用與意義啊.



1. Oracle 實(shí)例崩潰后, 內(nèi)存里的修改后數(shù)據(jù)并沒完全保存入硬盤


Oracle修改數(shù)據(jù), 是在Data buffer cache里修改的,? 一旦1個(gè)buffer被修改, 就成為了臟buffer, 所謂臟buffer意思就是指這個(gè)buffer跟磁盤里的對(duì)應(yīng)block的數(shù)據(jù)不同了.?? oracle的后臺(tái)進(jìn)程DBWR 會(huì)不斷地將Data buffer cache里的臟buffer 寫入硬盤.


但是當(dāng)數(shù)據(jù)庫(kù)突然崩潰的時(shí)候,? Datab buffer cache很可能還存在一些未寫入硬盤的臟數(shù)據(jù).?

就出現(xiàn)數(shù)據(jù)丟失.



2. 數(shù)據(jù)丟失也分兩種情況. ? ??

????????? 2.1? 可以丟失的數(shù)據(jù)

?????????? 意思就是這些數(shù)據(jù)丟失了沒關(guān)系, 不影響數(shù)據(jù)一致性.

?????????? 那么有什么數(shù)據(jù)是可以丟失呢,? 之前我們提過,? Oracle關(guān)于數(shù)據(jù)一致性有一個(gè)很重要的原則:

? ? ? ? ? ? ??? ??? Oralce會(huì)保證用戶已經(jīng)commit 的改動(dòng)不會(huì)丟失. ???????

?????????? 言下之意就是未提交的改動(dòng)就允許丟失了,? 其實(shí)邏輯上也是的,? 就例如用戶編輯1個(gè)execl文檔,? 但是并未保存, 這時(shí)突然windows死機(jī)..??? 你往excel文檔作的改動(dòng)就沒了,? 哎呀弄得我好像在黑微軟似的...? 那把windows死機(jī)改成突然斷電啦.

?

??????????? 總之就是Databuffer中未提交的臟buffer, 是允許丟失的.


???????? 2.2 不能丟失的數(shù)據(jù)

????????????這個(gè)很明顯啦,? 就是已經(jīng)commit, 但未被DBWR 寫入磁盤的臟buffer理論上是不允許丟失的, Oracle會(huì)有機(jī)制恢復(fù)這些臟buffer



3. 所以oracle利用日志找回一些臟buffer

? ? ? ? ? 這些臟buffer就是指上面已經(jīng)commit過的臟buffer啊.

????????? 通過什么來(lái)找回來(lái)呢,? 是同過修改日志啊.??

?????????? 那么修改日志在哪里呢?


??????????? 我們知道,? 但server process一但修改了1個(gè)buffer, 這個(gè)buffer 就臟了, 然后server process會(huì)同時(shí)將對(duì)應(yīng)的改動(dòng)日志寫入log buffer.

???????????? 而log buffer 既然是緩存, 肯定就是位于內(nèi)存中的啦,? 所以后臺(tái)進(jìn)程LGWR會(huì)不斷將log buffer里的日志寫入log 文件(硬盤)


?????????? 所以臟塊的修改日志的位置有兩個(gè)地方, 第1個(gè)就是在log buffer里,? 第2個(gè)就在log files里.


??????????? 我們之前也提過,? 用戶一但commit 1條transaction , 那么對(duì)應(yīng)這個(gè)transaction的修改日志就會(huì)被寫入到log files.

??????????? 也就是說(shuō)只有當(dāng)oracle把對(duì)應(yīng)日志從Log buffer 寫入到 log files完成時(shí), oracle才會(huì)提示用戶commit 完成!


???????????? 那么當(dāng)oracle 突然崩潰后,? log buffer里的日志全部就沒了,? 不過既然這些丟失日志是在log buffer 里的. 也代表這些日志對(duì)應(yīng)的改動(dòng)是未提交的,? 也就是logbuffer 里的日志丟失也沒關(guān)系,? 沒提交的改動(dòng)嘛

?

????????????? 那么已經(jīng)提交的改動(dòng), 日志都在log files里, 也就是重后還能找回來(lái)的, 既然日志能找回來(lái), 所以理論上那些已經(jīng)提交的臟buffer就能通過磁盤block 和日志重新構(gòu)造出來(lái)了.


4. Oracle 必須知道logfiles里對(duì)應(yīng)數(shù)據(jù)未寫入硬盤的日志的位置.

? ? ? ? ? ? ? ? 當(dāng)oracle 檢測(cè)出上次非正常關(guān)閉時(shí),? 就會(huì)執(zhí)行數(shù)據(jù)恢復(fù)動(dòng)作.


???????????????? 那么恢復(fù)的目標(biāo)是什么呢, 就是恢復(fù)到數(shù)據(jù)庫(kù)崩潰那個(gè)瞬間的狀態(tài)...

???????????????? 就會(huì)吧崩潰那個(gè)瞬間的已提交的臟buffer 都恢復(fù)出來(lái),??? 那么oracle就會(huì)去查找redo log files.(log buffer里的日志是未提交的, 就忽略了).?

????????????

????????????????? 好了, 但是redo log files里的日志很多啊, 都把他們對(duì)應(yīng)改動(dòng)恢復(fù)嗎?

????????????????? 當(dāng)然不是了, oracle 只會(huì)恢復(fù)那些未被DBWR 寫入的臟buffer(寫入里就變成干凈buffer了),? 實(shí)際上redo log files絕大部分日志對(duì)應(yīng)的改動(dòng)都已經(jīng)被寫入到data files.? 所以oracle 就會(huì)從redo log files找出一段 對(duì)應(yīng)數(shù)據(jù)未被DBWR寫入磁盤的日志.


???????????????? 那么這段日志在redo log file的哪里呢???

???????????????? 我們也提過oracle 是嚴(yán)格按照日志產(chǎn)生的時(shí)間(數(shù)據(jù)改動(dòng)的時(shí)間) 未順序去寫入 redo log files的,? 所以這段日志肯定就是log files里最新寫入的那一段了, 就是在日志文件的尾部啊.


??????????????? 好了, 所以到這里,? 這段日志的終點(diǎn)可以決定了, 就是log files 的最新的一條日志,??? 它的位置就是上文提到的on disk RBA啊.???

??????????????? 但是起點(diǎn)在哪里呢?


5. 可以通過 Checkpoint queue 找到最早未被寫入硬盤的臟塊buffer的日志位置.

???????????????回顧一下, checkpoint queue里的內(nèi)容:

? ? ? ? ? ? ? ?? checkpoint queue 是1個(gè)隊(duì)列,? 是以臟buffer的第一次被修改(變臟的時(shí)間) 為順序, 實(shí)際也是以臟buffer的LRBA地址(首次改動(dòng)的日志地址)的一條臟buffer鏈.

? ? ? ? ? ? ? ?? 可以理解出:

? ? ? ? ? ? ? ?? 1. 數(shù)據(jù)崩潰瞬間所有臟buffer都在 check point queue 上

? ? ? ? ? ? ? ?? 2.checkpoint queue的第1個(gè)臟buffer的首次變臟時(shí)間 在 數(shù)據(jù)庫(kù)崩潰瞬間里面所有臟buffer里的首次變臟時(shí)間里是最早的.

???????????????????? 也就是說(shuō)checkpoint queue排第一的那個(gè)buffer的LRBA 是整個(gè)數(shù)據(jù)庫(kù)中關(guān)于臟buffer的日志中最早的, 也是在日志文件中排的最前的.?? 這個(gè)LRBA 也是整個(gè)checkpoint queue 的LRBA


???????????????????


??????????????????? 如上圖, 整個(gè)checkpoint queue的LRBA 會(huì)比 on disk RBA早,?? 而on disk RBA 就是最新被寫入硬盤的那條日志地址, 所以 LRBA那個(gè)日志就肯定位于磁盤中了.


??????????????????? 那么整個(gè)checkpoint queue LRBA 前面那些日志是什么呢,? 首先那些地址比 checkpoint queue 的LRBA對(duì)應(yīng)日志產(chǎn)生時(shí)間要早.??

? ? ? ? ? ? ? ? ? ? 假如其中1個(gè)日志A, ? 他對(duì)應(yīng)的buffer 是 Buffer A, ? 如果這個(gè)日志A的地址在日志文件里比checkpoint queue? 靠前, 那么這個(gè)Buffer A 當(dāng)前肯定是1個(gè)干凈buffer了.

??????????????????????????? 怎么理解,? 假如這個(gè)Buffer A是臟的,? 那么肯定被掛在checkpoint queue 中, 而Buffer A的LRBA 的地址肯定早于或等于日志A,? 所以也肯定早于 checkpoint queue 的LRBA才對(duì),? 所以check point queue的LRBA應(yīng)該是Buffer A的LRBA啊, 所以就矛盾了, 由此可以反證出 checkpoint queue LRBA 前面的地址都是干凈buffer的日志.


??????????????????? 如下圖:



????????????????????? 所以我們想找的恢復(fù)日志的起點(diǎn)就是 checkpoint queue的最早buffer 的LRBA的地址啊,? 就如上圖 dirty buffer1 的日志1 的地址,???? 終點(diǎn)就是on disk RBA了, 所以數(shù)據(jù)庫(kù)恢復(fù)需要用到的日志就是 上圖 兩條虛線之間的日志啊

???????????????????? 當(dāng)然, 我們說(shuō)Logbuffer里面的日志丟失就丟失了, 因?yàn)樗麄儗?duì)應(yīng)的改動(dòng)都是未commit 的,?? 但是logfiles里面的( on disk RBA 與 checkpoint queue LRBA)之間的地址都是已經(jīng)commit的嗎?

???????????????????? 這個(gè)就不一定了, 因?yàn)閛racle 的LGWR每3秒會(huì)把 log buffer 里的數(shù)據(jù)寫入log file 一次,?所以這斷區(qū)間的日志對(duì)應(yīng)的buffer都有可能是未commit的.? 而且還有可能是干凈的, 例如上圖的dirty buffer2,? 假如DBWR 將dirty Buffer 2寫入db files,? 那么dirty buffer2就是一個(gè)干凈buffer了.? 而且它會(huì)被移除checkpoint queue(待考證, 因?yàn)殛?duì)列是只能從頭部移出, 尾部加入的)? 但是它的改動(dòng)日志還是會(huì)處于 我們要恢復(fù)日志的區(qū)間啊.


????????

6. oracle 崩潰中恢復(fù)時(shí)怎么找到checkpoint queue 的LRBA.


??????????????????? 上面我們已經(jīng)知道checkpoint queue 的LRBA地址的重要性了,? 它是用于恢復(fù)數(shù)據(jù)庫(kù)崩潰前臟buffer的起始日志位置啊.

??????????????????? 但是一旦數(shù)據(jù)庫(kù)崩潰, checkpoint queue本身就不存在了, (checkpoint queue 畢竟是一條由內(nèi)存buffer組成的隊(duì)列, 如果buffer都沒了, checkpoint queue也不會(huì)存在)?? 那么如何找到它的LRBA呢.


??????????????????? 這個(gè)就要參考上文中地提到的一點(diǎn):

??????????????????? 增量檢查點(diǎn)(incremental checkpoint):
??????????????????
這時(shí)CKPT 會(huì)將? check point queue第一個(gè)臟buffer 的 LRBA地址 記錄到控制文件中.


?????????????????? 這個(gè)事件每3秒一次, 也就是說(shuō)每3秒CKPT 進(jìn)程會(huì)更新一次控制文件的 checkpoint queu LRBA地址.

?????????????????? 所以oracle 崩潰只需要從控制文件找出 checkpoint queue的LRBA 就可以確定Logfiles中的對(duì)應(yīng)日志起點(diǎn)啦.


?????????????????? 也需要有人會(huì)問,? 既然增量檢查點(diǎn)每3秒發(fā)生一次,? 代表了崩潰后的控制文件的 checkpoint queue LRBA可能不是實(shí)時(shí)的, 會(huì)有問題嗎?


??????????????????? 我們?cè)俜治鲆幌?? 假如某個(gè)1個(gè)增量檢查點(diǎn)? checkpoint queue 的LRBA 是 A,?? 這時(shí)CKPT 把A 寫入了控制文件,? 好了, 這時(shí)過了1秒,? checkpoint queue 里的LRBA 變成了B,? 再過1秒,? 這時(shí)服務(wù)器崩潰了, 因?yàn)橄?個(gè)增量檢查點(diǎn)還沒發(fā)生, 所以控制文件里的LRBA 還是A,???? 而當(dāng)時(shí)checkpoint queue 的實(shí)時(shí)LRBA 是B,? 這樣會(huì)有問題嗎>


?????????????????? 這就要搞清楚 checkpoint queue 的內(nèi)容了,? 首先 checkpoint queue的 LRBA 是 checkpoint queue頭部第一個(gè)臟buffer? A的LRBA,? 如果這時(shí)? 這個(gè)LRBA更新了, 也就是代表頭部的臟buffer 變了,? 這時(shí)只有1種情況, 就是原來(lái)的LRBA 對(duì)應(yīng)的Buffer A被移出了 checkpoint queue, 為什么會(huì)被移除了, 只能是這個(gè)buffer A變干凈了啊.?


??????????????????? 返回剛才的情況, 雖然控制文件里的LRBA 不是 事實(shí)上的B, 已是之前的LRBA A,? 但是B的地址肯定會(huì)比A的遲,? 后果恢復(fù)時(shí)把干凈的Buffer A 也恢復(fù)出來(lái)了, 這個(gè)完全無(wú)傷大雅啊.

??????

??????????????????? 只不過為了避免恢復(fù)出太多多余的干凈buffer,? 所以才將增量檢查點(diǎn)設(shè)成每3秒一次啊.


7. oracle 崩潰中恢復(fù)時(shí)會(huì)根據(jù)日志恢復(fù)出已經(jīng)commit的臟buffer 和未commit 的臟buffer.

???????????????????? 在本文第5點(diǎn)提過了,? oracle用于數(shù)據(jù)恢復(fù)的日志中, 肯定包含了全部已經(jīng)commit 臟buffer 的日志,? 但是還會(huì)有一些未commit 臟buffer的日志.

???????????????????? 這樣的后果就是恢復(fù)時(shí)把所有已經(jīng)commit的臟buffer 全部恢復(fù)出來(lái)了,? 但是也會(huì)把一部分未提交的臟buffer 也恢復(fù)出來(lái).


????????????????????? 雖然恢復(fù)了一些多余的臟buffer, 但畢竟保證了commit過的臟buffer沒有丟失啊!? 所以還是能保持?jǐn)?shù)據(jù)一致性的原則的.

??????????????????

????????????????????? 而對(duì)于那些被恢復(fù)出來(lái)的多余的未提交的臟buffer, 為什么說(shuō)是多余的呢, 因?yàn)樾薷乃吹膕essions都不存在了, 所以oracle 會(huì)將它們?nèi)縭ollback ,? 返回干凈buffer的狀態(tài).



8. 假如沒有check point queue , 會(huì)有神馬后果?

????????????????? 到這里我們大概清楚checkpoint queue 是用來(lái)確定數(shù)據(jù)庫(kù)崩潰時(shí),? 跑日志的日志起點(diǎn)的

???????????????? 假如沒有這個(gè)check point queue , 那么oracle就確定不了數(shù)據(jù)庫(kù)崩潰前1 ~ 3秒的LRBA的起點(diǎn),? 所有只能把"所有"的日志用來(lái)跑一遍了.

???????????????? 日志跑多了怎么辦?? 例如 最舊日志是從10月1號(hào)保存的,? oracle10月15號(hào)崩潰,? 10月16號(hào)重啟恢復(fù), 如果把所有日志都跑一遍,?就跑到了10月1號(hào)的狀態(tài)了??

???????????????? 問題也不大, 因?yàn)槿罩具€存在嘛, 只需要把10月1號(hào)前滾到10月5號(hào)就ok啦.

?????????????????

????????????????? 但是這段恢復(fù)時(shí)間則很慢長(zhǎng)了, oracle 8i 之前就是沒有checkpoint queue的, 所以一旦崩潰, 下次開機(jī)恢復(fù)就很慢了.

????????????????? checkpoint queue的根本意義就是用來(lái)加快oracle 崩潰后恢復(fù)的速度啊!




最后總結(jié)下 oracle數(shù)據(jù)庫(kù)崩潰恢復(fù)到底做了什么:

前提: oracle 里一但1個(gè) transaction 被 commit, 那么對(duì)應(yīng)這個(gè)transaction的所有改動(dòng)日志都會(huì)從logbuffer 寫入log files(如果未寫入話)

1. oracle 啟動(dòng)時(shí)自檢發(fā)行上次不正常關(guān)閉

2. oracle 從控制文件找出最新的 checkpoint queue LRBA地址(運(yùn)行時(shí)每3秒一次增量檢查點(diǎn), 更新1次)

3. oracle會(huì)根據(jù) 起點(diǎn)為 上面的 LRBA? 終點(diǎn)為on disk RBA( 硬盤上最后1個(gè)日志地址) 這段區(qū)間內(nèi)的日志, 把對(duì)應(yīng)的buffer恢復(fù)出來(lái)( 也叫前滾 roll foward)

4. 目地是恢復(fù)出所有已經(jīng)commited 的所有臟buffer,? 對(duì)于那些被恢復(fù)出來(lái)的未commited 的臟buffer,? oracle 會(huì)將它們回滾.



??????????????????








????????????????????



















d

總結(jié)

以上是生活随笔為你收集整理的Oracle 实例崩溃恢复原理剖析 -- 检查点队列的作用与意义的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。