漫談PostgreSQL的日志實現(xiàn)機制 |
發(fā)布時間: 2012/7/26 16:57:44 |
1、事務(wù)的概念 事務(wù)是從實際生活中引入數(shù)據(jù)庫的一個概念,即事務(wù)內(nèi)的操作,要么全做,要么全不做。就像銀行轉(zhuǎn)賬一樣,當從一個帳戶轉(zhuǎn)出一部分錢之后,就必須在另一個帳戶中存入相同數(shù)目的錢,若是轉(zhuǎn)出錢之后,事務(wù)中止了,沒有在另一個帳戶中存錢,那么錢就不翼而飛了,這就是事務(wù)的原子性。當事務(wù)完成后,必須將其結(jié)果記錄下來,不然就無從知道事務(wù)是已經(jīng)發(fā)生還是尚未發(fā)生,這是事務(wù)的持久性。此外,事務(wù)還有隔離性和一致性。 2、為什么要引入日志? 首先,我們了解一下在數(shù)據(jù)庫中是如何實現(xiàn)一個事務(wù)的。當事務(wù)開始后,我們從磁盤中讀取數(shù)據(jù),然后對這些數(shù)據(jù)進行操作,可能是篩選、統(tǒng)計、更新等,還可以有一些新建數(shù)據(jù),總之,若發(fā)生數(shù)據(jù)變化后,當數(shù)據(jù)完成后,必須將這些變化后的數(shù)據(jù)重新寫入到磁盤中,這樣我們就完成了一個事務(wù)。當然這是最簡單的一個描述,下面我們來針對每個環(huán)節(jié)進行深入的分析。首先是從磁盤中讀取數(shù)據(jù),根據(jù)常識,我們知道,在一個應(yīng)用系統(tǒng)中,我們可能經(jīng)常會讀取相同的數(shù)據(jù),如果每次都從磁盤讀取,因為磁盤IO比較慢,所以效率不高,性能不好。大家都能想得到,可以采用緩沖區(qū)機制來提高數(shù)據(jù)讀取的性能。本文主要目的不是緩沖區(qū)就不多說了。接下來是對數(shù)據(jù)的操作,事務(wù)完成后,我們需要把更新后的數(shù)據(jù)寫入到磁盤,這里又有同樣的問題出現(xiàn),磁盤IO的性能問題,那么有人說我們還可以用緩沖區(qū)機制?說的太好了,緩沖區(qū)確實幫我們緩解了磁盤IO性能的問題。但緩沖區(qū)機制在幫我們解決了磁盤IO性能問題的同時,又帶來了一個新的問題,如果發(fā)生了故障怎么辦?如果數(shù)據(jù)庫系統(tǒng)能千秋萬載永世長存的話就沒問題了,但現(xiàn)實是不可能的,如果系統(tǒng)發(fā)生故障,比如斷電、死機什么的,緩沖區(qū)中的數(shù)據(jù)就會丟失,想想你剛中了500W元彩票,結(jié)果服務(wù)器down機了,你的彩票隨著緩沖區(qū)的消失隨風消逝了,你是不是很想把服務(wù)器給啃了?什么?你說你無所謂,一切都是浮云......別告訴我你是火星人...... 我們言歸正傳,在數(shù)據(jù)庫系統(tǒng)的設(shè)計中,數(shù)據(jù)的丟失是不可接受的,為了解決緩沖區(qū)數(shù)據(jù)寫入磁盤的性能問題,引入了日志。在操作數(shù)據(jù)之前,我們先將操作記入日志,然后再修改數(shù)據(jù),當然不修改數(shù)據(jù)的日志好象沒什么意義,這樣,即使系統(tǒng)down機導致緩沖區(qū)丟失,也不會把500W元彩票化為烏有了。我們可以通過讀取日志,重做丟失的數(shù)據(jù)的操作,就可以保證丟失的數(shù)據(jù)全部恢復(fù)。有人說,寫日志與寫緩沖區(qū)不是一樣要寫磁盤嗎?這位同學說的太對了,真的是一樣的,都要進行寫磁盤操作,只是有那么一點點細微的差別,寫日志是順序?qū)懭氪疟P,而緩沖區(qū)則是隨機寫入磁盤。雖然只是這一點點差別,但對性能的影響卻是巨大的,有興趣的同學可以自己去試試喲。此外日志的數(shù)據(jù)量也遠遠小于要寫入的緩沖區(qū)的數(shù)據(jù)量。 有些人提問了,為什么要先將操作記入日志,然后再執(zhí)行操作修改數(shù)據(jù)呢?這是因為若是先執(zhí)行操作,那么在隨后寫入日志之前若是系統(tǒng)down機,那么就會丟失此次操作,在數(shù)據(jù)庫系統(tǒng)中稱之為WAL(write ahead log)。 3、日志緩沖區(qū)的引入 為進一步提高性能,引入了日志緩沖區(qū),批量將日志寫入到磁盤,而不再是產(chǎn)生一條就寫一條,這樣又帶來一個問題,在日志緩沖區(qū)寫入磁盤之前有可能會導致日志丟失,從而導致數(shù)據(jù)丟失。如何解決這個問題呢?我們需要對日志的作用進一步分析,日志是為了重做丟失的操作,若一個事務(wù)未提交之前,那么這個事務(wù)已進行的操作實際上并不重要,即使丟失也沒有什么影響。就像銀行轉(zhuǎn)帳一樣,從一個賬戶已經(jīng)轉(zhuǎn)出,此時系統(tǒng)故障,無法對另一個帳戶轉(zhuǎn)入,此事務(wù)會回滾,即系統(tǒng)會退回到帳戶轉(zhuǎn)出之前的狀態(tài),賬戶轉(zhuǎn)出操作無效,即使賬戶轉(zhuǎn)出的操作這條日志未被寫入磁盤導致操作丟失,當我們恢復(fù)時,并不會有什么影響,可能還加速了恢復(fù)的過程,少處理了一條日志。因此日志緩沖區(qū)的磁盤寫入時機可以被推遲,最晚不能晚于事務(wù)提交。實際上在日志緩沖區(qū)實現(xiàn)上還有一些其它的限制,如checkpoint、日志緩沖區(qū)已滿等,不一定要等到事務(wù)提交時才寫入磁盤。 4、lsn的由來和作用 既然已經(jīng)有了日志,就要發(fā)揮它的作用,在恢復(fù)過程中,通過讀取日志來重做操作,按什么順序來重做日志呢?記錄歷史操作的順序,是非常重要的,如果操作順序發(fā)現(xiàn)混亂,導致的后果也是非常嚴重的。比如對一個數(shù)值100先減去100,再翻倍,若是發(fā)生操作順序逆轉(zhuǎn),先翻倍再減去100,得到的結(jié)果就大相徑庭了。這里就需要一個規(guī)則,給日志編個序號,我們按日志產(chǎn)生的順序給每條日志編號,然后按日志編號來重做日志,就不會發(fā)生日志重做發(fā)生混亂的情況。在實現(xiàn)的過程中,我們在記錄日志的時候,是按日志產(chǎn)生的順序依次寫入磁盤的,即使是寫到日志緩沖區(qū)中,也是按產(chǎn)生的順序依次寫到日志緩沖區(qū),再將日志緩沖區(qū)順序?qū)懙酱疟P中。因此我們可以采用日志在日志文件中的偏移來代替這個日志編號,不僅不需要額外的磁盤開銷,而且還能通過這個偏移迅速定位到這個日志,真是個神奇的想法,我們給這樣的日志編號起了一個特殊的名字:lsn,這就是lsn的由來。 但我們又發(fā)現(xiàn)一個新的問題,雖然我們知道了所有的歷史操作和它們之間的順序關(guān)系,但不知道這些操作的影響是否已經(jīng)保存到磁盤,如果簡單的重做所有操作,會不會把已經(jīng)做過的操作重復(fù)進行。比如購物轉(zhuǎn)賬轉(zhuǎn)了兩次錢出去?所以在每個數(shù)據(jù)塊的塊頭記錄下最后一次修改這個數(shù)據(jù)塊的操作的日志編號lsn,當重做日志時,數(shù)據(jù)塊加載到緩沖區(qū)中,稱之為頁面,若頁面的header中l(wèi)sn比當前重做日志的lsn小,則說明當前日志尚未被重做; 若不比當前重做日志的lsn小,即大于或等于當前重做日志的lsn,則說明當前日志已經(jīng)被重做,或不需要重做;通過這種方法,可以避免日志被重復(fù)重做,從而得到正確的恢復(fù)結(jié)果。 5、利用checkpoint加速恢復(fù)的過程 當系統(tǒng)發(fā)生故障后,由于有日志的存在我們不用擔心數(shù)據(jù)丟失,可以通過讀取日志來恢復(fù),但若是系統(tǒng)已經(jīng)運行了很長時間,操作很多,日志很大的情況下,在進行日志恢復(fù)時恢復(fù)進程會十分慢長。在生產(chǎn)環(huán)境下,要求恢復(fù)的時間越短越好,怎么才能縮短恢復(fù)的時間呢?checkpoint就是解決這個問題的辦法。在日志中,引入一種特殊的日志類型,checkpoint日志,它表示在此之前的所有“臟數(shù)據(jù)”已經(jīng)寫入到磁盤,那么在它之前的日志在恢復(fù)過程中就可以忽略掉,而不用再處理。雖然我們希望checkpoint是一個瞬時的過程,但在實現(xiàn)上卻有很大的難度,我們不能瞬時將所有“臟數(shù)據(jù)”寫入磁盤,如果可以做到,也就不需要日志了。因此checkpoint是一個過程,有它的起始和結(jié)束,當checkpoint開始時,我們記錄當前日志的記錄偏移lsn,并標記所有的“臟數(shù)據(jù)”為準備寫入狀態(tài),接下來就是將具有準備寫入狀態(tài)的”臟數(shù)據(jù)”寫入磁盤,注意:在寫入的同時其它進程或線程有可能會產(chǎn)生新的“臟數(shù)據(jù)”,這些新產(chǎn)生的“臟數(shù)據(jù)”我們并不關(guān)心其是否寫入磁盤。當所有已標記的“臟數(shù)據(jù)”寫入磁盤之后,在日志中插入一條checkpoint日志,表示checkpoint已經(jīng)完成,同時它還記錄著checkpoint開始時的日志偏移,也稱為REDO偏移。當進行恢復(fù)時,首先找到最后一次checkpoint日志的位置,讀出checkpoint日志記錄,從中獲得REDO偏移,然后從REDO偏移開始恢復(fù)即可。通過調(diào)整checkpoint的間隔時間,可以得到一個可接受的故障恢復(fù)時間。 本文出自:億恩科技【1tcdy.com】 服務(wù)器租用/服務(wù)器托管中國五強!虛擬主機域名注冊頂級提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM] |