關於持久性
持久性是指,事務提交后,對系統的影響必須是永久的,即使系統意外宕機,也必須確保事務提交時的修改已真正永久寫入到永久存儲中。
最簡單的實現方法,當然是在事務提交后立即刷新事務修改后的數據到磁盤。但是磁盤和內存之間的IO操作是最影響數據庫系統影響時間的,一有事務提交就去刷新磁盤,會對數據庫性能產生不好影響。
WAL機制的引入,即保證了事務持久性和數據完整性,又盡量地避免了頻繁IO對性能的影響。
WAL過程分析
Write-Ahead Logging,前寫日志。
在MVCC的部分中,我們已經分析了PostgreSQL的存儲結構:元組-文件頁-物理段-表;
以及寫數據的步驟:先寫到緩沖區Buffer-再刷新到磁盤Disk。
WAL機制實際是在這個寫數據的過程中加入了對應的寫wal log的過程,步驟一樣是先到Buffer,再刷新到Disk。
- Change發生時:
- 先將變更后內容記入WAL Buffer
- 再將更新后的數據寫入Data Buffer
- Commit發生時:
- WAL Buffer刷新到Disk
- Data Buffer寫磁盤推遲
- Checkpoint發生時:
- 將所有Data Buffer刷新到磁盤


WAL的好處
通過上面的分析,可以看到:
當宕機發生時,
- Data Buffer的內容還沒有全部寫入到永久存儲中,數據丟失;
- 但是WAL Buffer的內容已寫入磁盤,根據WAL日志的內容,可以恢復庫丟失的內容。
在提交時,僅把WAL刷新到了磁盤,而不是Data刷新:
- 從IO次數來說,WAL刷新是少量IO,Data刷新是大量IO,WAL刷新次數少得多;
- 從IO花銷來說,WAL刷新是連續IO,Data刷新是隨機IO,WAL刷新花銷小得多。
因此WAL機制在保證事務持久性和數據完整性的同時,成功地提升了系統性能。
附:PostgreSQL官網文檔關於WAL的翻譯
官網翻譯
Write-Ahead Logging是一種保證數據完整性的標准方法。簡單地說,WAL的概念就是對數據文件的改變(包括表和索引)必須先寫入日志,即日志記錄刷新到永久儲存之后,才能被寫。遵循這個過程,就不需要在每個事務提交時都刷新數據頁到磁盤,因為在宕機時可以用日志來恢復數據庫:任何沒有應用到數據頁上的改動都可以根據日志記錄重做。(即回滾恢復REDO)
因為WAL可以在宕機后恢復數據庫文件內容,JFS(journaled file systems)對於數據文件或WAL文件的可靠存儲就不是必要的了。實際上,JFS甚至會影響系統性能,尤其當它要把文件系統數據刷新到磁盤的時候。還好,JFS中的數據刷新可以在文件系統掛載選項中禁用。JFS確實提高了宕機后的root速度。
使用WAL可以顯著地減少寫磁盤的次數,因為只需要把日志文件刷新到磁盤就可以保證事務被提交,而不需要把事務改動過的每一個數據文件都刷新到磁盤。日志文件是連續寫的,所以同步log的花銷遠小於刷新數據頁的花銷。特別是服務器要處理涉及數據存儲不同部分的大量小事務時更是這樣。另外,當服務器在處理大量並行小事務時,log文件一次fsync就可以提交多個事務。
WAL還使得在線備份和時間點恢復成為可能。通過歸檔WAL數據,我們可以恢復到WAL數據覆蓋范圍內的任何時間點:只需install一份數據庫的物理備份,並恢復WAL日志到所需時間即可。更重要的是,這個物理備份並不必須是一個數據庫狀態的瞬時快照——如果一段時間的快照,那把WAL日志也恢復成那一段時間的即可。
PostgreSQL的WAL原理和Oracle、SQL Server 相似。