新聞中心
在我撰寫 High-Performance Java Persistence training 一書時,我逐步認識到讓讀者明白關(guān)系型數(shù)據(jù)庫工作原理會是了解如何構(gòu)建高性能的 Java 持久化存儲的重要基石。不過關(guān)系型數(shù)據(jù)庫中的事務(wù)相關(guān)的重要概念:原子性、持久性以及檢查點等等也是相當繞人。而本文中我希望以相對高屋建瓴的方式來解釋關(guān)系型數(shù)據(jù)庫內(nèi)部工作原理,也會涉及一些數(shù)據(jù)庫實現(xiàn)細節(jié)。

在網(wǎng)站制作、成都網(wǎng)站制作過程中,需要針對客戶的行業(yè)特點、產(chǎn)品特性、目標受眾和市場情況進行定位分析,以確定網(wǎng)站的風(fēng)格、色彩、版式、交互等方面的設(shè)計方向。創(chuàng)新互聯(lián)建站還需要根據(jù)客戶的需求進行功能模塊的開發(fā)和設(shè)計,包括內(nèi)容管理、前臺展示、用戶權(quán)限管理、數(shù)據(jù)統(tǒng)計和安全保護等功能。
Data Pages
訪問磁盤中的數(shù)據(jù)往往速度較慢,換言之,內(nèi)存中數(shù)據(jù)的訪問速度還是遠快于 SSD 中的數(shù)據(jù)訪問速度?;谶@個考量,基本上所有數(shù)據(jù)庫引擎都盡可能地避免訪問磁盤數(shù)據(jù)。并且無論數(shù)據(jù)庫表還是數(shù)據(jù)庫索引都被劃分為了固定大小的數(shù)據(jù)頁(譬如 8 KB)。當我們需要讀取表或者索引中的數(shù)據(jù)時,關(guān)系型數(shù)據(jù)庫會將磁盤中的數(shù)據(jù)頁映射入存儲緩沖區(qū)。當我們需要修改數(shù)據(jù)時,關(guān)系型數(shù)據(jù)庫首先會修改內(nèi)存頁中的數(shù)據(jù),然后利用 fsync) 這樣的同步工具將改變同步回磁盤中。
Undo log
由于同時可能由多個事務(wù)并發(fā)地對內(nèi)存中的數(shù)據(jù)進行修改,因此關(guān)系型數(shù)據(jù)庫往往需要依賴于某個并發(fā)控制機制(2PL 或者 MVCC)來保證數(shù)據(jù)一致性。因此,當某個事務(wù)需要去更改數(shù)據(jù)表中某一行時,未提交的改變會被寫入到內(nèi)存數(shù)據(jù)中,而之前的數(shù)據(jù)會被追加寫入到 undo log 文件中。
Oracle 或者 MySQL 中使用了所謂 undo log 數(shù)據(jù)結(jié)構(gòu),而SQL Server 中則是使用 transaction log 完成此項工作。PostgreSQL 并沒有 undo log,不過其內(nèi)建支持所謂多版本的表數(shù)據(jù),即同一行的數(shù)據(jù)可能同時存在多個版本??偠灾?,任何關(guān)系型數(shù)據(jù)庫都采用的類似的數(shù)據(jù)結(jié)構(gòu)都是為了允許回滾以及數(shù)據(jù)的原子性。
如果當前運行的事務(wù)發(fā)生了回滾,undo log 會被用于重建事務(wù)起始階段時候的內(nèi)存頁。
Redo Log
某個事務(wù)提交之后,內(nèi)存中的改變就需要同步到磁盤中。不過并不是所有的事務(wù)提交都會立刻觸發(fā)同步,過高頻次的同步反而會對應(yīng)用性能造成損傷。不過根據(jù) ACID 原則,提交之后的事務(wù)必須要保證持久性,也就是即使此時數(shù)據(jù)庫引擎宕機了,提交之后的更改也應(yīng)該被持久化存儲下來。這里關(guān)系型數(shù)據(jù)庫就是依靠 redo log 來達成這一點,它是一個僅允許追加寫入的基于磁盤的數(shù)據(jù)結(jié)構(gòu),它會記錄所有尚未執(zhí)行同步的事務(wù)操作。相較于一次性寫入固定數(shù)目的數(shù)據(jù)頁到磁盤中,順序地寫入到 redo log 會比隨機訪問快上很多。因此,關(guān)于事務(wù)的 ACID 特性的保證與應(yīng)用性能之間也就達成了較好的平衡。該數(shù)據(jù)結(jié)構(gòu)在 Oracle 與 MySQL 中就是叫 redo log,而 SQL Server 中則是由 transaction log 執(zhí)行,在 PostgreSQL 中則是使用 Write-Ahead Log( WAL )。
下面我們繼續(xù)回到上面的那個問題,應(yīng)該在何時將內(nèi)存中的數(shù)據(jù)寫入到磁盤中。關(guān)系型數(shù)據(jù)庫系統(tǒng)往往使用檢查點來同步內(nèi)存的臟數(shù)據(jù)頁與磁盤中的對應(yīng)部分。為了避免 IO 阻塞,同步過程往往需要等待較長的時間才能完成。因此,關(guān)系型數(shù)據(jù)庫需要保證即使在所有內(nèi)存臟頁同步到磁盤之前引擎就崩潰的時候不會發(fā)生數(shù)據(jù)丟失。同樣地,在每次數(shù)據(jù)庫重啟的時候,數(shù)據(jù)庫引擎會基于 redo log 重構(gòu)那些***一次成功的檢查點以來所有的內(nèi)存數(shù)據(jù)頁。
總結(jié)
上面我們簡要討論的這些原則與考慮都是為了保證基于磁盤的存儲的較高吞吐量的同時保證數(shù)據(jù)一致性。其中,undo lo 主要用于提供原子性(允許回滾),而 redo log 則是保證磁盤頁的不可變性。
【本文是專欄作者“張梓雄 ”的原創(chuàng)文章,如需轉(zhuǎn)載請通過與作者聯(lián)系】
戳這里,看該作者更多好文
名稱欄目:關(guān)系型數(shù)據(jù)庫工作原理簡述
當前鏈接:http://m.fisionsoft.com.cn/article/djpedsi.html


咨詢
建站咨詢
