數據庫事務的實現(一) 故障恢復 (undo日志)


前言

事務是數據庫中的重要組成部分。針對於事務本身的介紹,大家可以google下其他文章。本篇文章的目的不在於介紹事務是什么,而重點想描述的是事務是如何實現的。所以本篇文章及接下來的幾篇文章都是描述數據庫系統中事務的實現,希望通過這幾篇文章將自己的知識做一下總結,當然,如果在總結的同時,可以給各位朋友帶來相應的益處那是最好的了。如果文章有不妥之處,歡迎各位朋友指正。

簡介

保證數據的一致性是數據庫的一個最最基本的功能,那數據庫在機器down機或者出現其他意外的情況下是如何去保證數據庫的數據的一致性的呢?本文主要圍繞這個話題,介紹undo日志和redo日志這兩種保持數據一致性的機制。undolog和redolog是數據庫的兩種日志文件,數據庫正是利用這兩種日志文件去實現數據的一致性。

數據庫架構簡介

要介紹數據庫一致性的實現機制,自然少不了要介紹下數據庫的整體架構,這里畫一個簡圖來介紹下數據庫的架構。

數據庫架構簡圖

我們將數據庫簡化,主要分這么幾塊:

  • 查詢處理器,主要負責針對於查詢sql的解析、執行計划的選擇等等。
  • 事務管理器,事務是數據庫操作的最小單位,事務管理器主要針對於分配事務id等等管理工作
  • 日志管理器
  • 恢復管理器
  • 緩沖管理器,這個大家也清楚,數據庫中的寫操作都是在緩沖器中完成,然后再flush到硬盤上。
  • 硬盤數據,日志 無論是數據庫的數據、還是日志文件,都是最終要寫到硬盤上做持久化存儲的。

下面就針對於上面說的這幾塊組成部分,來描述下數據庫是如何做災難恢復的。這一篇主要還是講undolog,下一篇再講redolog。

undo日志簡介

undo日志,顧名思義,就是撤銷日志,也就是說,這個日志里面記錄了相關的撤銷操作。通過剛才的數據庫架構簡圖,我們也可以看到,針對於寫數據等處理主要還是在內存中進行,既然在內存中進行,那就會出現由於機器宕機導致的丟數據問題。那數據庫是如何通過undo日志去保證數據的一致性的呢?

要描述這個問題,我們需要先定義幾種操作。假設我們現在要做這樣一件事情,需要把某條數據X從數據庫中讀出來,然后再去改變他的值,改為Y,然后再寫回去。好,這樣一個操作,數據庫可能要走這樣幾個流程,首先會看緩沖區里有沒有,假設有則直接將數據返回,我們稱這樣一個過程為Read(X),假設緩沖區里沒有,那就需要先從硬盤讀到緩沖區,然后再返回給用戶,那我們定義從硬盤讀到緩沖區的過程為Input(X),也就是說,如果緩沖區里沒有,那數據庫要先經過一個Read(X),然后再經過一個Input(X),然后再經過一個Read(X)。那修改時也一樣,數據庫要修改緩沖區的內容,那這個操作我們成為Write(Y).還要經過一個從內存刷到磁盤的過程,這個過程我們成為output(Y)。好,有了這幾個定義,我們就挨個從這幾個過程去分析,如果數據庫再這中間某個過程掛了,如何去保證數據的一致性。

在介紹前,先簡要說下undolog日志的格式,undolog日志的格式是這樣的 <T,A,X>,T就代表事務ID,A就代表某一行的某一列,X就代表原先的值。也就是說這條日志就代表T這個事務時,A原先的值為X,對,undolog僅僅記錄原先的值,他並不關心你把它改成了多少,他關心的就是原先是多少,因為將來只是做撤銷工作。除了這個之外,undolog中還記錄start ,意為開啟一個事務,commit,意為提交一個事務。大體我們就可以先抽象成這幾個。

那比如我們要做上面那個問題,即讀取一個值再修改(假設不在緩沖區中),那就要經過以下幾步:

見表格:

編號 操作 undolog
1 start
2 Read(X)
3 Input(X)
4 Read(X)
5 Write(Y)
6 <T,A,X>
7 flush undolog  
8 Output(Y)
9
10 commit
11 end
10 flush undolog  

我們看上面這個表格,下面我就解釋下這個表格。 首先,我們需要明確的一點是,無論是操作數據庫中的數據,還是日志,都是先在內存中操作,然后flush到硬盤上。這一點是毫無疑問的。

前4步應該都容易理解,一開始在undolog中需要記錄一個start的標志位,然后2、3、4步都是讀取數據庫的內容,第5步往內存中寫,將X的值改為Y,然后第6步undolog中會記錄下事務T中A的原先值是X,那到了第7步呢? 是到底是應該先將undolog進行flush,還是應該output后再flush呢?

我們做個假設,假設output后再進行log的flush,如果恰好就在output后,數據庫down機了,那這樣的結果顯而易見,日志文件里並沒有記載undolog(因為沒有flush到硬盤),無法重做所以就會導致數據不一致。所以要在output后進行undolog的flush是不可取的。

那我們看下上面這個順序的意義,假設在第6-7步之間宕機了,也就就是在還未flush undolog時已宕機,那不會影響數據的一致性,因為本來數據就沒有寫到硬盤。如果是在第7-8步間宕機,雖然數據庫的數據沒有寫到硬盤,但log已經flush了,那這時會通過flush后的log重做一遍,因為系統不知道這個log做過了沒有,不過即使是重做一遍也不影響最終的數據一致性,也只是將原先的數據又重新寫了一遍而已,就是從X寫為X,這個不影響數據庫一致性,undolog是冪等的,也就是做幾次的結果都是一樣。所以上面這個順序才是合理的。

通過undolog進行數據恢復

既然有了undolog,那我們看下數據庫是如何通過undolog進行數據恢復的。這時上面架構簡圖里的恢復管理器就起了作用了,恢復管理器會掃描undolog,找出沒有end掉的start,因為從上面的順序中我們可以看出,“end”記錄flush到log中是在事務提交后才flush的,所以,只要是有了end記錄了,就說明了這個事務本身已經結束了,數據一致性已經可以保證了。所以恢復管理器這時是掃描沒有end配位的start,然后從start開始往后,根據undolog中記錄的先前的值進行重做。不過根據我們剛才這個模型會發現,在恢復管理器進行重做時,是不能有其他的寫入的,也就是現在的寫入應該是夯住狀態的。而且還有個問題,恢復管理器需要從頭開始對於undolog進行掃描,其實這是不必須的,完全可以有個checkpoint(代表在這之前的數據已經可以保證數據一致性了)的,那恢復管理器只需要找到最后一個checkpoint,然后從checkpoint往后做就可以了。

針對於以上這兩個問題,我們下一篇文章數據庫事務的實現-故障恢復(二)(undo日志檢查點)再討論,這篇就先到這吧。要干點別的了。

希望本文會對大家有幫助。

 

本文來自於http://www.log4myself.info/archives/287


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM