關係型數據庫工做原理簡述

關係型數據庫工做原理簡述 翻譯自 VLADMIHALCEA 的 How does a relational database work,從屬於筆者的 服務端基礎架構入門與實踐。本文只是寥寥數言的關係型數據庫工做流程簡述,關於關係型數據庫工做原理的詳細介紹建議閱讀 ChristopheHow does a relational database workgit

概述

在我撰寫 High-Performance Java Persistence training 一書時,我逐步認識到讓讀者明白關係型數據庫工做原理會是瞭解如何構建高性能的 Java 持久化存儲的重要基石。不過關係型數據庫中的事務相關的重要概念:原子性、持久性以及檢查點等等也是至關繞人。而本文中我但願以相對高屋建瓴的方式來解釋關係型數據庫內部工做原理,也會涉及一些數據庫實現細節。github

Data Pages

訪問磁盤中的數據每每速度較慢,換言之,內存中數據的訪問速度仍是遠快於 SSD 中的數據訪問速度。基於這個考量,基本上全部數據庫引擎都儘量地避免訪問磁盤數據。而且不管數據庫表仍是數據庫索引都被劃分爲了固定大小的數據頁(譬如 8 KB)。當咱們須要讀取表或者索引中的數據時,關係型數據庫會將磁盤中的數據頁映射入存儲緩衝區。當咱們須要修改數據時,關係型數據庫首先會修改內存頁中的數據,而後利用 fsync) 這樣的同步工具將改變同步回磁盤中。數據庫

Undo log

因爲同時可能由多個事務併發地對內存中的數據進行修改,所以關係型數據庫每每須要依賴於某個併發控制機制(2PL 或者 MVCC)來保證數據一致性。所以,當某個事務須要去更改數據表中某一行時,未提交的改變會被寫入到內存數據中,而以前的數據會被追加寫入到 undo log 文件中。數據結構

Oracle 或者 MySQL 中使用了所謂 undo log 數據結構,而SQL Server 中則是使用 transaction log 完成此項工做。PostgreSQL 並無 undo log,不過其內建支持所謂多版本的表數據,即同一行的數據可能同時存在多個版本。總而言之,任何關係型數據庫都採用的相似的數據結構都是爲了容許回滾以及數據的原子性。架構

若是當前運行的事務發生了回滾,undo log 會被用於重建事務起始階段時候的內存頁。併發

Redo Log

某個事務提交以後,內存中的改變就須要同步到磁盤中。不過並非全部的事務提交都會馬上觸發同步,太高頻次的同步反而會對應用性能形成損傷。不過根據 ACID 原則,提交以後的事務必需要保證持久性,也就是即便此時數據庫引擎宕機了,提交以後的更改也應該被持久化存儲下來。這裏關係型數據庫就是依靠 redo log 來達成這一點,它是一個僅容許追加寫入的基於磁盤的數據結構,它會記錄全部還沒有執行同步的事務操做。相較於一次性寫入固定數目的數據頁到磁盤中,順序地寫入到 redo log 會比隨機訪問快上不少。所以,關於事務的 ACID 特性的保證與應用性能之間也就達成了較好的平衡。該數據結構在 Oracle 與 MySQL 中就是叫 redo log,而 SQL Server 中則是由 transaction log 執行,在 PostgreSQL 中則是使用 Write-Ahead Log( WAL )。
下面咱們繼續回到上面的那個問題,應該在什麼時候將內存中的數據寫入到磁盤中。關係型數據庫系統每每使用檢查點來同步內存的髒數據頁與磁盤中的對應部分。爲了不 IO 阻塞,同步過程每每須要等待較長的時間才能完成。所以,關係型數據庫須要保證即便在全部內存髒頁同步到磁盤以前引擎就崩潰的時候不會發生數據丟失。一樣地,在每次數據庫重啓的時候,數據庫引擎會基於 redo log 重構那些最後一次成功的檢查點以來全部的內存數據頁。mvc

總結

上面咱們簡要討論的這些原則與考慮都是爲了保證基於磁盤的存儲的較高吞吐量的同時保證數據一致性。其中,undo lo 主要用於提供原子性(容許回滾),而 redo log 則是保證磁盤頁的不可變性。ide

相關文章
相關標籤/搜索