關系型數(shù)據(jù)庫工作原理簡述
在我撰寫 High-Performance Java Persistence training 一書時,我逐步認識到讓讀者明白關系型數(shù)據(jù)庫工作原理會是了解如何構建高性能的 Java 持久化存儲的重要基石。不過關系型數(shù)據(jù)庫中的事務相關的重要概念:原子性、持久性以及檢查點等等也是相當繞人。而本文中我希望以相對高屋建瓴的方式來解釋關系型數(shù)據(jù)庫內部工作原理,也會涉及一些數(shù)據(jù)庫實現(xiàn)細節(jié)。
Data Pages
訪問磁盤中的數(shù)據(jù)往往速度較慢,換言之,內存中數(shù)據(jù)的訪問速度還是遠快于 SSD 中的數(shù)據(jù)訪問速度。基于這個考量,基本上所有數(shù)據(jù)庫引擎都盡可能地避免訪問磁盤數(shù)據(jù)。并且無論數(shù)據(jù)庫表還是數(shù)據(jù)庫索引都被劃分為了固定大小的數(shù)據(jù)頁(譬如 8 KB)。當我們需要讀取表或者索引中的數(shù)據(jù)時,關系型數(shù)據(jù)庫會將磁盤中的數(shù)據(jù)頁映射入存儲緩沖區(qū)。當我們需要修改數(shù)據(jù)時,關系型數(shù)據(jù)庫首先會修改內存頁中的數(shù)據(jù),然后利用 fsync) 這樣的同步工具將改變同步回磁盤中。
Undo log
由于同時可能由多個事務并發(fā)地對內存中的數(shù)據(jù)進行修改,因此關系型數(shù)據(jù)庫往往需要依賴于某個并發(fā)控制機制(2PL 或者 MVCC)來保證數(shù)據(jù)一致性。因此,當某個事務需要去更改數(shù)據(jù)表中某一行時,未提交的改變會被寫入到內存數(shù)據(jù)中,而之前的數(shù)據(jù)會被追加寫入到 undo log 文件中。
Oracle 或者 MySQL 中使用了所謂 undo log 數(shù)據(jù)結構,而SQL Server 中則是使用 transaction log 完成此項工作。PostgreSQL 并沒有 undo log,不過其內建支持所謂多版本的表數(shù)據(jù),即同一行的數(shù)據(jù)可能同時存在多個版本??偠灾?,任何關系型數(shù)據(jù)庫都采用的類似的數(shù)據(jù)結構都是為了允許回滾以及數(shù)據(jù)的原子性。
如果當前運行的事務發(fā)生了回滾,undo log 會被用于重建事務起始階段時候的內存頁。
Redo Log
某個事務提交之后,內存中的改變就需要同步到磁盤中。不過并不是所有的事務提交都會立刻觸發(fā)同步,過高頻次的同步反而會對應用性能造成損傷。不過根據(jù) ACID 原則,提交之后的事務必須要保證持久性,也就是即使此時數(shù)據(jù)庫引擎宕機了,提交之后的更改也應該被持久化存儲下來。這里關系型數(shù)據(jù)庫就是依靠 redo log 來達成這一點,它是一個僅允許追加寫入的基于磁盤的數(shù)據(jù)結構,它會記錄所有尚未執(zhí)行同步的事務操作。相較于一次性寫入固定數(shù)目的數(shù)據(jù)頁到磁盤中,順序地寫入到 redo log 會比隨機訪問快上很多。因此,關于事務的 ACID 特性的保證與應用性能之間也就達成了較好的平衡。該數(shù)據(jù)結構在 Oracle 與 MySQL 中就是叫 redo log,而 SQL Server 中則是由 transaction log 執(zhí)行,在 PostgreSQL 中則是使用 Write-Ahead Log( WAL )。
下面我們繼續(xù)回到上面的那個問題,應該在何時將內存中的數(shù)據(jù)寫入到磁盤中。關系型數(shù)據(jù)庫系統(tǒng)往往使用檢查點來同步內存的臟數(shù)據(jù)頁與磁盤中的對應部分。為了避免 IO 阻塞,同步過程往往需要等待較長的時間才能完成。因此,關系型數(shù)據(jù)庫需要保證即使在所有內存臟頁同步到磁盤之前引擎就崩潰的時候不會發(fā)生數(shù)據(jù)丟失。同樣地,在每次數(shù)據(jù)庫重啟的時候,數(shù)據(jù)庫引擎會基于 redo log 重構那些***一次成功的檢查點以來所有的內存數(shù)據(jù)頁。
總結
上面我們簡要討論的這些原則與考慮都是為了保證基于磁盤的存儲的較高吞吐量的同時保證數(shù)據(jù)一致性。其中,undo lo 主要用于提供原子性(允許回滾),而 redo log 則是保證磁盤頁的不可變性。
【本文是51CTO專欄作者“張梓雄 ”的原創(chuàng)文章,如需轉載請通過51CTO與作者聯(lián)系】

















 
 
 







 
 
 
 