【wal】你常聽說的WAL到底是什么?

什么是 WAL

數(shù)據(jù)庫中一種高效的日志算法,對(duì)于非內(nèi)存數(shù)據(jù)庫而言,磁盤I/O操作是數(shù)據(jù)庫效率的一大瓶頸。

在相同的數(shù)據(jù)量下,采用WAL日志的數(shù)據(jù)庫系統(tǒng)在事務(wù)提交時(shí),磁盤寫操作只有傳統(tǒng)的回滾日志的一半左右,大大提高了數(shù)據(jù)庫磁盤I/O操作的效率,從而提高了數(shù)據(jù)庫的性能。

WAL(Write Ahead Log)預(yù)寫日志,是數(shù)據(jù)庫系統(tǒng)中常見的一種手段,用于保證數(shù)據(jù)操作的原子性和持久性。

在計(jì)算機(jī)科學(xué)中,「預(yù)寫式日志」(Write-ahead logging,縮寫 WAL)是關(guān)系數(shù)據(jù)庫系統(tǒng)中用于提供原子性和持久性(ACID 屬性中的兩個(gè))的一系列技術(shù)。

在使用 WAL 的系統(tǒng)中,所有的修改在提交之前都要先寫入 log 文件中。

log 文件中通常包括 redo 和 undo 信息,這樣做的目的可以通過一個(gè)例子來說明。
假設(shè)一個(gè)程序在執(zhí)行某些操作的過程中機(jī)器掉電了,在重新啟動(dòng)時(shí),程序可能需要知道當(dāng)時(shí)執(zhí)行的操作是成功了還是部分成功或者是失敗了。

如果使用了 WAL,程序就可以檢查 log 文件,并對(duì)突然掉電時(shí)計(jì)劃執(zhí)行的操作內(nèi)容跟實(shí)際上執(zhí)行的操作內(nèi)容進(jìn)行比較。在這個(gè)比較的基礎(chǔ)上,程序就可以決定是撤銷已做的操作還是繼續(xù)完成已做的操作,或者是保持原樣。

WAL 允許用 in-place 方式更新數(shù)據(jù)庫。另一種用來實(shí)現(xiàn)原子更新的方法是 shadow paging,它并不是 in-place 方式。用 in-place 方式做更新的主要優(yōu)點(diǎn)是減少索引和塊列表的修改。

ARIES 是 WAL 系列技術(shù)常用的算法。
在文件系統(tǒng)中,WAL 通常稱為 journaling。
PostgreSQL 也是用 WAL 來提供 point-in-time 恢復(fù)和數(shù)據(jù)庫復(fù)制特性。

image.png

計(jì)算機(jī)中所有的問題都可以通過添加一個(gè)中間層來解決。

備份

如果想保證對(duì)一個(gè)數(shù)據(jù)的操作可以恢復(fù),可以怎么做?

你不用去想數(shù)據(jù)庫是怎么實(shí)現(xiàn)的,也不用想太高深。其實(shí)這是一個(gè)很簡單的問題,我們常常在處理這種問題。最簡單的方法其實(shí)就是備份一份數(shù)據(jù):當(dāng)我需要對(duì)一條數(shù)據(jù)做更新操作前,先將這條數(shù)據(jù)備份在一個(gè)地方,然后去更新,如果更新失敗,可以從備份數(shù)據(jù)中回寫回來。這樣就可以保證事務(wù)的回滾,就可以保證數(shù)據(jù)操作的原子性了。

其實(shí) SQLite 引入 WAL 之前就是通過這種方式來實(shí)現(xiàn)原子事務(wù),稱之為 rollback journal, rollback journal 機(jī)制的原理是:在修改數(shù)據(jù)庫文件中的數(shù)據(jù)之前,先將修改所在分頁中的數(shù)據(jù)備份在另外一個(gè)地方,然后才將修改寫入到數(shù)據(jù)庫文件中;如果事務(wù)失敗,則將備份數(shù)據(jù)拷貝回來,撤銷修改;如果事務(wù)成功,則刪除備份數(shù)據(jù),提交修改。

WAL

如何做到數(shù)據(jù)的可恢復(fù)(原子性)和提交成功的數(shù)據(jù)被持久化到磁盤(持久性)?

另一種機(jī)制就是WAL,WAL 機(jī)制的原理也很簡單:「修改并不直接寫入到數(shù)據(jù)庫文件中,而是寫入到另外一個(gè)稱為 WAL 的文件中;

如果事務(wù)失敗,WAL 中的記錄會(huì)被忽略,撤銷修改;

如果事務(wù)成功,它將在隨后的某個(gè)時(shí)間被寫回到數(shù)據(jù)庫文件中,提交修改?!?/p>

WAL 的優(yōu)點(diǎn):

  1. 讀和寫可以完全地并發(fā)執(zhí)行,不會(huì)互相阻塞(但是寫之間仍然不能并發(fā))。
  2. WAL 在大多數(shù)情況下,擁有更好的性能(因?yàn)闊o需每次寫入時(shí)都要寫兩個(gè)文件)。
  3. 磁盤 I/O 行為更容易被預(yù)測。
  4. 使用更少的 fsync()操作,減少系統(tǒng)脆弱的問題。

性能提升

我們都知道,數(shù)據(jù)庫的最大性能挑戰(zhàn)就是磁盤的讀寫,許多人在提供數(shù)據(jù)存儲(chǔ)性能上絞盡腦汁,提出和實(shí)驗(yàn)了一套又一套方法。

其實(shí)所有方案最終總結(jié)出來就三種:「隨機(jī)讀寫改順序讀寫」、「緩沖單條讀寫改批量讀寫」、「單線程讀寫改并發(fā)讀寫」。

WAL 其實(shí)也是這兩種思路的一種實(shí)現(xiàn),一方面 WAL 中記錄事務(wù)的更新內(nèi)容,通過 WAL 將隨機(jī)的臟頁寫入變成順序的日志刷盤,另一方面,WAL 通過 buffer 的方式改單條磁盤刷入為緩沖批量刷盤,再者從 WAL 數(shù)據(jù)到最終數(shù)據(jù)的同步過程中可以采用并發(fā)同步的方式。這樣極大提升數(shù)據(jù)庫寫入性能,因此,WAL 的寫入能力決定了數(shù)據(jù)庫整體性能的上限,尤其是在高并發(fā)時(shí)。

checkpoint

上面講到,使用 WAL 的數(shù)據(jù)庫系統(tǒng)不會(huì)再每新增一條 WAL 日志就將其刷入數(shù)據(jù)庫文件中,一般積累一定的量然后批量寫入,通常使用「頁」為單位,這是磁盤的寫入單位。

同步 WAL 文件和數(shù)據(jù)庫文件的行為被稱為 checkpoint(檢查點(diǎn)),一般在 WAL 文件積累到一定頁數(shù)修改的時(shí)候;

當(dāng)然,有些系統(tǒng)也可以手動(dòng)執(zhí)行 checkpoint。執(zhí)行 checkpoint 之后,WAL 文件可以被清空,這樣可以保證 WAL 文件不會(huì)因?yàn)樘蠖阅芟陆怠?/p>

有些數(shù)據(jù)庫系統(tǒng)讀取請(qǐng)求也可以使用 WAL,通過讀取 WAL 最新日志就可以獲取到數(shù)據(jù)的最新狀態(tài)。

為什么要使用WAL呢?

真正的執(zhí)行操作可能數(shù)據(jù)量會(huì)比較大,操作比較繁瑣,并且寫數(shù)據(jù)不一定是順序?qū)懀匀绻恳淮尾僮鞫家却Y(jié)果flush到可靠存儲(chǔ)(比如磁盤)中才執(zhí)行下一步操作的話,效率就太低了。

換一種思路,如果我們?cè)谧稣嬲牟僮髦?,先將這件事記錄下來,持久化到可靠存儲(chǔ)中(因?yàn)槿罩疽话愫苄?,并且是順序?qū)?,效率很高),然后再去?zhí)行真正的操作。

這樣執(zhí)行真正操作的時(shí)候也就不需要等待執(zhí)行結(jié)果flush到磁盤再執(zhí)行下一步,因?yàn)闊o論在哪一步出錯(cuò),我們都能夠根據(jù)備忘錄重做一遍,得到正確的結(jié)果。

參考

PostgreSQL WAL日志解析與應(yīng)用
https://doc.huodongjia.com/detail-2388.html

你常聽說的WAL到底是什么?
https://www.cnblogs.com/xuwc/p/14037750.html

WAL(預(yù)寫式日志)簡介
https://lessisbetter.site/2020/01/02/wal-introduction

數(shù)據(jù)庫如何使用預(yù)寫式日志(Write Ahead Log, WAL) 解決 IO 問題的?
https://blog.csdn.net/universsky2015/article/details/100528607

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原子提交 原子提交(Atomic Commits)是SQLite這種事務(wù)型數(shù)據(jù)庫的一個(gè)重要特性。原子提交意味著單個(gè)...
    PerTerbin閱讀 7,814評(píng)論 1 8
  • 預(yù)寫式日志,是關(guān)系型數(shù)據(jù)庫中用于保證原子性和持久性(ACID)的一系列技術(shù)。在使用WAL的系統(tǒng)中,所有修改在提交之...
    瑾瑾寶寶閱讀 1,506評(píng)論 0 0
  • 關(guān)于持久性 持久性是指,事務(wù)提交后,對(duì)系統(tǒng)的影響必須是永久的,即使系統(tǒng)意外宕機(jī),也必須確保事務(wù)提交時(shí)的修改已真正永...
    ZYJ2016閱讀 8,788評(píng)論 0 4
  • 多個(gè)應(yīng)用程序或者同一個(gè)應(yīng)用程序的多個(gè)例程能同時(shí)存取同一個(gè)數(shù)據(jù)庫文件嗎? 多進(jìn)程可以同時(shí)打開同一個(gè)數(shù)據(jù)庫,也可以同時(shí)...
    woshishui1243閱讀 916評(píng)論 0 0
  • YYKVStorage 上一篇介紹了操作文件的api,接下來介紹數(shù)據(jù)庫。 - (BOOL)_dbOpen { i...
    充滿活力的早晨閱讀 797評(píng)論 0 0

友情鏈接更多精彩內(nèi)容