qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

          oracle深度解析檢查點(diǎn)

            由于中LGWR和DBWR工作的不一致,Oracle引入了檢查點(diǎn)的概念,用于同步,保證數(shù)據(jù)庫(kù)的一致性。在Oracle里面,檢查點(diǎn)分為兩種:完全檢查點(diǎn)和增量檢查點(diǎn)。下面我們分別介紹這兩種檢查點(diǎn)的作用:

            1、完全檢查點(diǎn)

            在Oracle8i之前,數(shù)據(jù)庫(kù)的發(fā)生的檢查點(diǎn)都是完全檢查點(diǎn),完全檢查點(diǎn)會(huì)將數(shù)據(jù)緩沖區(qū)里面所有的臟數(shù)據(jù)塊寫入相應(yīng)的數(shù)據(jù)文件中,并且同步數(shù)據(jù)文件頭和控制文件,保證數(shù)據(jù)庫(kù)的一致。完全檢查點(diǎn)在8i之后只有在下列兩種情況下才會(huì)發(fā)生:

            (1)DBA手工執(zhí)行alter system checkpoint的命令;

            (2)數(shù)據(jù)庫(kù)正常shutdown(immediate,transcational,normal)。

            由于完全檢查點(diǎn)會(huì)將所有的臟數(shù)據(jù)庫(kù)塊寫入,巨大的IO往往會(huì)影響到數(shù)據(jù)庫(kù)的性能。因此Oracle從8i開(kāi)始引入了增量檢查點(diǎn)的概念。

            2、增量檢查點(diǎn)

            Oracle 從8i開(kāi)始引入了檢查點(diǎn)隊(duì)列這么一種概念,用于記錄數(shù)據(jù)庫(kù)里面當(dāng)前所有的臟數(shù)據(jù)塊的信息,DBWR 根據(jù)這個(gè)隊(duì)列而將臟數(shù)據(jù)塊寫入到數(shù)據(jù)文件中。檢查點(diǎn)隊(duì)列按時(shí)間先后記錄著數(shù)據(jù)庫(kù)里面臟數(shù)據(jù)塊的信息,里面的條目包含RBA(Redo Block Address,重做日志里面用于標(biāo)識(shí)檢查點(diǎn)期間數(shù)據(jù)塊在重做日志里面第一次發(fā)生更改的編號(hào))和數(shù)據(jù)塊的數(shù)據(jù)文件號(hào)和塊號(hào)。在檢查點(diǎn)期間不論數(shù)據(jù)塊更改幾次,它在檢查點(diǎn)隊(duì)列里面的位置始終保持不變,檢查點(diǎn)隊(duì)列也只會(huì)記錄它最早的RBA,從而保證最早更改的數(shù)據(jù)塊能夠盡快寫入。當(dāng)DBWR將檢查點(diǎn)隊(duì)列里面的臟數(shù)據(jù)塊寫入到數(shù)據(jù)文件后,檢查點(diǎn)的位置也要相應(yīng)地往后移,CKPT每三秒會(huì)在控制文件中記錄檢查點(diǎn)的位置,以表示Instance Recovery時(shí)開(kāi)始恢復(fù)的日志條目,這個(gè)概念稱為檢查點(diǎn)的“心跳”(heartbeat)。檢查點(diǎn)位置發(fā)生變更后,Oracle里面通過(guò)4個(gè)參數(shù)用于控制檢查點(diǎn)位置和最后的重做日志條目之間的距離。在這里面需要指出的是,多數(shù)人會(huì)將這4個(gè)參數(shù)看作控制增量檢查點(diǎn)發(fā)生的時(shí)間。事實(shí)上這是錯(cuò)誤的,這4個(gè)參數(shù)是用于控制檢查點(diǎn)隊(duì)列里面的條目數(shù)量,而不是控制檢查點(diǎn)的發(fā)生。

            (1)fast_start_io_target

            該參數(shù)用于表示數(shù)據(jù)庫(kù)發(fā)生Instance Recovery的時(shí)候需要產(chǎn)生的IO總數(shù),它通過(guò)v$filestat的AVGIOTIM來(lái)估算的。比如我們一個(gè)數(shù)據(jù)庫(kù)在發(fā)生Instance Crash后需要在10分鐘內(nèi)恢復(fù)完畢,假定OS的IO每秒為500個(gè),那么這個(gè)數(shù)據(jù)庫(kù)發(fā)生Instance Recovery的時(shí)候大概將產(chǎn)生500*10*60=30,000次IO,也就是我們將可以把fast_start_io_target設(shè)置為 30000。

            (2)fast_start_mttr_target

            我們從上面可以看到fast_start_io_target 來(lái)估算檢查點(diǎn)位置比較麻煩。Oracle為了簡(jiǎn)化這個(gè)概念,從9i開(kāi)始引入了 fast_start_mttr_target這么一個(gè)參數(shù),用于表示數(shù)據(jù)庫(kù)發(fā)生Instance Recovery的時(shí)間,以秒為單位。這個(gè)參數(shù)我們從字面上也比較好理解,其中的mttr是mean time to recovery的簡(jiǎn)寫,如上例中的情況我們可以將fast_start_mttr_target設(shè)置為600。當(dāng)設(shè)置了 fast_start_mttr_target后,fast_start_io_target這個(gè)參數(shù)將不再生效,從9i后 fast_start_io_target這個(gè)參數(shù)被Oracle廢除了。

            (3)log_checkpoint_timeout

            該參數(shù)用于表示檢查點(diǎn)位置和重做日志文件末尾之間的時(shí)間間隔,以秒為單位,默認(rèn)情況下是1800秒。

            (4)log_checkpoint_interval

            該參數(shù)是表示檢查點(diǎn)位置和重做日志末尾的重做日志塊的數(shù)量,以O(shè)S塊表示。

            (5)90% OF SMALLEST REDO LOG

            除了以上4個(gè)初始化參數(shù)外,Oracle內(nèi)部事實(shí)上還將重做日志文件末尾前面90%的位置設(shè)為檢查點(diǎn)位置。在每個(gè)重做日志中,這么幾個(gè)參數(shù)指定的位置可能不盡相同,Oracle將離日志文件末尾最近的那個(gè)位置確認(rèn)為檢查點(diǎn)位置。

            oracle 9i instance recovery

            1、增量檢查點(diǎn)

            在checkpoint queue的基礎(chǔ)上實(shí)現(xiàn)了增量檢查點(diǎn),每3秒發(fā)生一次checkpoint heartbeat,記錄dbwr上次寫成功的最大RBA(redo block address)。這樣的話做instance recovery的時(shí)候就從這個(gè)rba開(kāi)始,而不是從上次checkpoint scn開(kāi)始,大大節(jié)省了恢復(fù)時(shí)間。


          2、twice scan of redo log

            在應(yīng)用redo之前,redo將會(huì)被操作兩次,第一次去掃描哪些redo record需要被應(yīng)用,因?yàn)?i在redo里添加了dbwr寫數(shù)據(jù)塊的信息,所以dbwr發(fā)生前的日志將不會(huì)被應(yīng)用。第二步就是選出需要被應(yīng)用的日志然后開(kāi)始rollforward。

            3、rollforward

            在做instance recovery時(shí)必須先定位到redo log 然后應(yīng)用所有日志到datafile,這時(shí)候包括了committed和uncommitted的數(shù)據(jù)。當(dāng)做完rollward,數(shù)據(jù)庫(kù)就可以open了。

            4、rollback

            因 為rollforward產(chǎn)生了uncommitted數(shù)據(jù),所以必須回滾這些數(shù)據(jù)。這將由smon和on-demand rollback來(lái)實(shí)現(xiàn)。smon將會(huì)掃描undo segment header去標(biāo)志所有活動(dòng)事務(wù)為dead,然后會(huì)逐漸去回滾這些事務(wù)。另外on-demand rollback提供了前臺(tái)進(jìn)程進(jìn)行rollback,當(dāng)前臺(tái)進(jìn)程企圖獲得被dead事務(wù)占用row lock,這時(shí)候前臺(tái)進(jìn)程將會(huì)去undo segment取得before image去回滾這個(gè)塊,至于其他被這個(gè)dead事務(wù)lock的塊就等待smon去回滾。

            另外,如果 在數(shù)據(jù)庫(kù)打開(kāi)的過(guò)程中process crash導(dǎo)致transaction dead,resource不能被釋放的情況,這時(shí)候如果另一個(gè)進(jìn)程需要這些resource,那么這個(gè)進(jìn)程將會(huì)等待直到pmon清理dead process釋放出resource。

            如果數(shù)據(jù)庫(kù)Crash,重新啟動(dòng),很久遠(yuǎn)以前的未提交事務(wù)并不在Redo的恢復(fù)序列中。

            但是未提交事務(wù)一定在回滾段事務(wù)表上存在,并且State=10,為活動(dòng)事務(wù)。這就夠了。

            數(shù)據(jù)庫(kù)啟動(dòng)之后,這些事務(wù)會(huì)被SMON逐個(gè)標(biāo)記為Dead(不可能再活過(guò)來(lái)了),然后由SMON慢慢去回滾這些事務(wù);也存在另外一種情況,后來(lái)的進(jìn)程會(huì)去讀這些未提交數(shù)據(jù),發(fā)現(xiàn)Dead事務(wù)未提交,則主動(dòng)進(jìn)行回滾。

            1、一個(gè)數(shù)據(jù)塊發(fā)生更新,必然寫回滾

            2、回滾段的block變化也記錄在redo中

            一份未提交的數(shù)據(jù)必定在回滾中有相應(yīng)的前鏡像,任何正常的恢復(fù)都一定會(huì)把這些變化重新構(gòu)建出來(lái)。

            想像一下

            1、update事務(wù)1更新了block 1

            2、回滾段1記錄了block1的前鏡像

            3、checkpoint

            4、update事務(wù)2更新了block2

            5、回滾段2記錄了block2的前鏡像

            6、instance crash

            現(xiàn)在重啟數(shù)據(jù)庫(kù)

            1、根據(jù)redo重新構(gòu)建block2

            2、根據(jù)redo重新構(gòu)建回滾段2

            3、database open

            4、SMON用回滾段2的數(shù)據(jù)回滾block2,SMON用回滾段1的數(shù)據(jù)回滾block1

            最后一步也可能是

            在另外一個(gè)select檢索到block1或者block2的時(shí)候,發(fā)現(xiàn)這兩個(gè)block的數(shù)據(jù)都是未提交的,此時(shí)再回滾block1和block2。

            所以,只要有相應(yīng)的回滾數(shù)據(jù)存在,無(wú)論什么時(shí)候oracle都可以找到一致的數(shù)據(jù),oracle只需要知道這個(gè)事務(wù)是提交了的還是沒(méi)提交了的,而這點(diǎn)在block header ITL中有記錄。

           

          posted on 2011-11-30 11:00 順其自然EVO 閱讀(1791) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2011年11月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 安阳县| 浦江县| 彰化县| 齐齐哈尔市| 江华| 边坝县| 莱西市| 延寿县| 许昌县| 额尔古纳市| 海原县| 海伦市| 夏津县| 泸定县| 彭州市| 息烽县| 甘洛县| 聂拉木县| 高台县| 望谟县| 蒙山县| 来凤县| 高青县| 淄博市| 喀喇沁旗| 绥化市| 家居| 沐川县| 虹口区| 理塘县| 涡阳县| 鄂伦春自治旗| 文安县| 巴东县| 鲜城| 池州市| 舞阳县| 八宿县| 玉门市| 平山县| 依兰县|