什么是wal日志
先看一段官方文檔
預寫式日志(WAL)是保證數據完整性的一種標准方法。對其詳盡的描述幾乎可以在所有(如果不是全部)有關事務處理的書中找到。簡單來說,WAL的中心概念是數據文件(存儲着表和索引)的修改必須在這些動作被日志記錄之后才被寫入,即在描述這些改變的日志記錄被刷到持久存儲以后。如果我們遵循這種過程,我們不需要在每個事務提交時刷寫數據頁面到磁盤,因為我們知道在發生崩潰時可以使用日志來恢復數據庫:任何還沒有被應用到數據頁面的改變可以根據其日志記錄重做(這是前滾恢復,也被稱為REDO)。
使用WAL可以顯著降低磁盤的寫次數,因為只有日志文件需要被刷出到磁盤以保證事務被提交,而被事務改變的每一個數據文件則不必被刷出。日志文件被按照順序寫入,因此同步日志的代價要遠低於刷寫數據頁面的代價。在處理很多影響數據存儲不同部分的小事務的服務器上這一點尤其明顯。此外,當服務器在處理很多小的並行事務時,日志文件的一個fsync
可以提交很多事務。
WAL也使得在線備份和時間點恢復能被支持,通過歸檔WAL數據,我們可以支持回轉到被可用WAL數據覆蓋的任何時間:我們簡單地安裝數據庫的一個較早的物理備份,並且重放WAL日志一直到所期望的時間。另外,該物理備份不需要是數據庫狀態的一個一致的快照 — 如果它的制作經過了一段時間,則重放這一段時間的WAL日志將會修復任何內部不一致性。
- wal_level = replica (pg13默認已經開啟replica)
該參數的可選的值有minimal,replica和logical,wal的級別依次增高,在wal的信息也越多。由於minimal這一級別的wal不包含從基礎的備份和wal日志重建數據的足夠信息,在該模式下,無法開啟wal日志歸檔
如何開啟歸檔
在生產環境,為了保證數據高可用性,通常需要設置歸檔,所謂的歸檔,其實就是把pg_wal里面的日志備份出來,當系統故障后可以通過歸檔的日志文件對數據進行恢復:
配置歸檔需要開啟如下參數:
wal_level = replica或者logical
- archive_mode = on
上述參數為on,表示打開歸檔備份,可選的參數為on,off,always 默認值為off,所以要手動打開 - archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
該參數的默認值是一個空字符串,他的值可以是一條shell命令或者一個復雜的shell腳本。在shell腳本或命令中可以用 “%p” 表示將要歸檔的wal文件包含完整路徑的信息的文件名,用“%f” 代表不包含路徑信息的wal文件的文件名
注意:wal_level和archive_mode參數修改都需要重新啟動數據庫才可以生效。而修改archive_command則不需要。所以一般配置新系統時,無論當時是否需要歸檔,這要建議將這兩個參數開啟
當啟用archive_mode
時,可以通過設置 archive_command命令將完成的 WAL 段發送到 歸檔存儲。除用於禁用的off
之外,還有兩種模式: on
和always
。在普通操作期間,這兩種模式之間 沒有區別,但是當設置為always
時,WAL 歸檔器在歸檔恢復 或者后備模式下也會被啟用。在always
模式下,所有從歸檔恢復 的或者用流復制傳來的文件將被(再次)歸檔。詳見 第 26.2.9 節。
archive_mode
和archive_command
是獨立的變量,這樣可以在不影響歸檔模式的前提下修改archive_command
。這個參數只能在服務器啟動時設置。當wal_level
被設置為minimal
時,archive_mode
不能被啟用。
需要注意的是archive_mode=on后,如果不設置archive_command則不會生成歸檔,而是在pg_wal/archive_status 目錄下生成.done的空文件,只是說明這個歸檔已經完成,其實並沒有真正的歸檔文件
切換歸檔
通過select pg_switch_xlog()或select pg_switch_wal();可以手動切換xlog/wal日志。
PG10之前版本:select pg_switch_xlog();
PG10開始版本:select pg_switch_wal();
官網關於歸檔的相關解釋
本地 shell 命令被執行來歸檔一個完成的 WAL 文件段。字符串中的任何%p
被替換成要被歸檔的文件的路徑名, 而%f
只被文件名替換(路徑名是相對於服務器的工作目錄, 即集簇的數據目錄)。如果要在命令里嵌入一個真正的%
字符,可以使用%%
。有一點很重要,該命令只在成功時返回一個零作為退出狀態。更多信息請見第 25.3.1 節。
這個參數只能在postgresql.conf
文件中或在服務器命令行上設置。除非服務器啟動時啟用了archive_mode
,否則它會被忽略。如果archive_mode
被啟用時,archive_command
是一個空字符串(默認),WAL 歸檔會被臨時禁用,但服務器仍會繼續累計 WAL 段文件,期待着一個命令被提供。將archive_command
設置為一個只返回真但不做任何事的命令(例如/bin/true
或 Windows 上的REM
)實際上會禁用歸檔,也會打破歸檔恢復所需的 WAL 文件鏈,因此只有在極少數情況下才能用。
archive_command僅在已完成的 WAL 段上調用。因此,如果你的服務器只產生很少的 WAL 流量(或產生流量的周期很長),那么在事務完成和它被安全地記錄到歸檔存儲之間將有一個很長的延遲。為了限制未歸檔數據存在的時間,你可以設置archive_timeout
來強制服務器來周期性地切換到一個新的 WAL 段文件。 當這個參數被設置為大於零時,只要從上次段文件切換后過了參數所設置的時間量,並且已經有過任何數據庫活動(包括一個單一檢查點),服務器將切換到一個新的段文件(如果沒有數據庫活動則會跳過檢查點)。 注意,由於強制切換而提早關閉的被歸檔文件仍然與完整的歸檔文件長度相同。因此,使用非常短的archive_timeout
是不明智的 — 它將占用巨大的歸檔存儲。一分鍾左右的archive_timeout
設置通常比較合理。如果你希望數據能被更快地從主服務器上復制下來,你應該考慮使用流復制而不是歸檔。如果指定值時沒有單位,則以秒為單位。這個參數只能在postgresql.conf
文件中或在服務器命令行上設置。