先看下進程
關於持久性的概念
持久性是指,事務提交后,對系統的影響必須是永久的,即使系統意外宕機,也必須確保事務提交時的修改已真正永久寫入到永久存儲中。
簡單來講,我往銀行存了100塊錢,這個存錢流程走完了之后,銀行必須保證我存的100塊錢一直都在,能查詢到,能取出來。
持久性如何實現
最簡單的實現方法,當然是在事務提交后立即刷新事務修改后的數據到磁盤。但是磁盤和內存之間的IO操作是最影響數據庫系統影響時間的,一有事務提交就去刷新磁盤,會對數據庫性能產生較大影響。
WAL機制的引入,即保證了事務持久性和數據完整性,又盡量地避免了頻繁IO對性能的影響。
WalWriter進程
WalWriter進程是一個后端進程,它負責確保WAL文件被正確寫入磁盤,並且它的行為可以在postgresql.conf中設置以下參數進行配置:
#------------------------------------------------------------------------------ # WRITE-AHEAD LOG #------------------------------------------------------------------------------ # - Settings - #wal_level = replica # minimal, replica, or logical # (change requires restart) #fsync = on # flush data to disk for crash safety # (turning this off can cause # unrecoverable data corruption) #synchronous_commit = on # synchronization level; # off, local, remote_write, remote_apply, or on #wal_sync_method = fsync # the default is the first option # supported by the operating system: # open_datasync # fdatasync (default on Linux) # fsync # fsync_writethrough # open_sync #full_page_writes = on # recover from partial page writes #wal_compression = off # enable compression of full-page writes #wal_log_hints = off # also do full page writes of non-critical updates # (change requires restart) #wal_init_zero = on # zero-fill new WAL files #wal_recycle = on # recycle WAL files #wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers # (change requires restart) #wal_writer_delay = 200ms # 1-10000 milliseconds #wal_writer_flush_after = 1MB # measured in pages, 0 disables #wal_skip_threshold = 2MB #commit_delay = 0 # range 0-100000, in microseconds #commit_siblings = 5 # range 1-1000
【wal_level】
控制wal存儲的級別。wal_level確定有多少信息被寫入到WAL。默認值是replica,它添加了WAL歸檔信息,包括只讀服務器(流復制)所需的信息。還可以將其設置為minimal,即只寫入從崩潰或立即關閉中恢復所需的信息。設置為Logical允許在邏輯解碼場景中完成WAL流。
【fsync】
這個參數直接控制日志是否先寫到磁盤。默認值為ON(先寫),這意味着系統應該通過發出wal_sync_method設置的fsync指令,來確保更改確實被刷新到磁盤。雖然關閉fsync通常可以提高性能,其直接隱患是無法保證在系統崩潰時最近的事務能夠得到恢復,也就無法保證相關數據的真實與正確性
【synchronous_commit】
此參數用於配置系統是否等待WAL完全完成后再將狀態信息返回給用戶事務。默認值為ON,表示必須等待WAL完成后才能返回事務狀態信息;配置OFF可以更快地反饋事務狀態,提升性能。
【wal_sync_method】
這個參數控制WAL寫入磁盤的fsync方法。默認值是fsync。可用的值包括open_datasync、fdatasync、fsync_writethrough、fsync、以及open_sync.open_datasync和open_sync,一般采用默認值即可,對於裸設備或文件系統的可選配置,在實際的使用中所帶來的方便相對fsync很有限。
【full_page_writes】
指示是否將整個頁面寫入WAL,參數表明是否將整個page寫入WAL。postgresql中數據處理過程中的位置只有內存和WAL中,在內存中的整個page中己包含更新提交的也包含沒有提交的,如果不將整個page寫入WAL中,在介質恢復的時候WAL中記錄的數據不足以實現完整的恢復(說白了就是無法實現介質恢復時事務的回滾),寫入整個page。
說到這里似乎更明白了,postgresql中不存在類似oracle的undo文件,postgresql將前滾和回滾所需的數據都寫入到了WAL。不管是否寫入整個page,對數據庫的PITR不影響(文檔也說明了),因為更新提交肯定要寫入了WAL中。
【wal_buffers】
指示了用於存儲WAL數據的內存空間量。系統默認值為64K。此參數還受wal_writer_delay和commit_delay這兩個參數的影響。
【wal_writer_delay】
WalWriter進程的寫入間隔。默認值是200毫秒。如果時間過長,可能會導致WAL緩沖區內存不足;如果時間太短,會導致WAL不斷寫入,增加磁盤I/O負擔。
【wal_writer_flush_after】
當臟數據超過這個閾值時,它將被刷新到磁盤。
【commit_delay】
指示在WAL buffer中存儲已提交的數據的時間。默認值為0毫秒,表示沒有延遲;當它被設置為非零值時,在事務提交后,事務將不會被立即寫入到WAL中,但它仍然存儲在WAL buffer中,等待WalWriter進程定期寫入磁盤。
【commit_siblings】
當事務發出提交請求時,如果數據庫中的事務數量大於commit_sibling的值,事務將等待一段時間(commit_delay值);否則,事務將直接寫入到WAL。系統默認值是5,這個參數還確定了commit_delay的有效性。
WAL如何工作
WAL機制實際是在這個寫數據的過程中加入了對應的寫WAL log的過程,步驟一樣是先到Buffer,再刷新到Disk。
Change發生時:
-
先將變更后內容記入WAL Buffer
-
再將更新后的數據寫入Data Buffer
Commit發生時:
-
WAL Buffer刷新到Disk
-
Data Buffer寫磁盤推遲
Checkpoint發生時:
-
將所有Data Buffer刷新到磁盤
Change時:
Commit和Checkpoint時: