PostgreSQL WAL 冪等性詳解

1. WAL簡介

WAL(Write-Ahead Logging)是PostgreSQL的核心機制之一。其基本理念是:在修改數據庫數據頁之前,必須先將這次修改操作寫入到WAL日志中。
這確保了即使發生崩潰,數據庫也可以根據WAL日志進行恢復。

恢復的核心流程就是不斷**Replay(重做)**WAL記錄,把數據庫恢復到一致狀態。

2. 為什么需要冪等性?

故障恢復可能發生在任意時刻,且可能反復進行。為了確保數據一致性,必須保證:

  • WAL重放(replay)是冪等的:即多次重做同樣的WAL記錄,最終結果與只做一次是一樣的。
  • 防止重復執行邏輯修改,避免出現臟數據(如重復插入、更新錯誤等)。

沒有冪等性,PostgreSQL的可靠性和數據完整性就無從談起。

3. PostgreSQL 如何實現 WAL 的冪等性?

分情況討論:

3.1 物理日志(Full Page Write, FPW)

  • 當首次修改某個page時,如果遇到檢查點之后第一次修改,或者出現了部分寫(partial write)風險時,PostgreSQL會將整個page的物理鏡像寫入WAL。
  • 恢復時直接拷貝覆蓋,無需考慮page上的狀態。
  • 因為是整頁覆蓋,所以天然是冪等的。重復應用多次,結果不會變。

注:FPW是恢復的"大殺器",確保即使發生中間頁損壞,也能恢復。

3.2 邏輯日志(Insert/Update/Delete操作記錄)

  • 日志并不是直接記錄"修改了page的哪一塊物理位置",而是記錄在什么page上執行了什么邏輯操作。
  • 例如:在某個page上插入一條tuple "X",而不是"在page偏移offset=32的地方插入"。
  • 如果簡單地無腦重做,恢復兩遍就會出現重復記錄。

為避免此問題,PostgreSQL每個page在物理結構中維護了一個字段:pd_lsn,即Page LSN。

  • 當一個page被修改時,它的pd_lsn被更新為當前WAL record的LSN。
  • 恢復時,每次要重放一個WAL record之前,PostgreSQL會先檢查:
    只有當 WAL record 的 LSN > page 的 pd_lsn 時,才進行重做,否則跳過

3.3 流程示意圖

恢復 -> 讀取WAL record -> 找到要修改的Page ->

比較 (WAL record LSN vs Page pd_lsn)

?? -> 如果 WAL LSN <= Page LSN, 說明已經做過,跳過

?? -> 如果 WAL LSN > Page LSN, 執行修改,更新Page LSN

這種機制可以保證:即使崩潰后在同一個地方反復重做日志,也不會對數據造成破壞。

4. 實驗驗證 PostgreSQL WAL 冪等性

下面用一個小實驗驗證pg的WAL冪等性:

4.1 實驗環境準備

initdb -D /tmp/pgwaltest

pg_ctl -D /tmp/pgwaltest -l logfile start

psql

4.2 創建表并插入數據

CREATE TABLE test_wal (id serial PRIMARY KEY, val text);

INSERT INTO test_wal(val) VALUES('first insert');

CHECKPOINT;? -- 強制生成檢查點,防止混入無關WAL

這時test_wal表中有一條數據,系統生成了新的檢查點。

4.3 查看Page LSN

PostgreSQL提供了擴展 pageinspect 來查看物理Page的信息。

安裝并使用:

CREATE EXTENSION pageinspect;

-- 找出表的物理文件

SELECT relfilenode FROM pg_class WHERE relname = 'test_wal';

-- 假設relfilenode是 16384

-- 查看page的LSN(第一頁)

SELECT * FROM page_header(get_raw_page('test_wal', 0));

會返回:

lsn? | checksum | flags | lower | upper | special | pagesize | version | prune_xid

------+----------+-------+-------+-------+---------+----------+---------+-----------

0/1500720 |??? ...?? |?????? |?? ... |?? ... |??? ...?? |??? 8192? |??? 4??? |??? ...

記錄下當前Page的LSN,比如是0/1500720。

4.4 模擬崩潰后重復恢復

手動重放WAL當然很復雜,但可以模擬:

  1. 手動修改page LSN,使其低于WAL日志的LSN;
  2. 重啟數據庫,觸發recovery。

不過這樣太麻煩,我們可以簡單理解為:

  • 如果page LSN已經大于WAL record的LSN,那么即使WAL被Replay,也不會改動頁面。

4.5 直接實驗重復寫入一條相同數據:

-- 模擬意外重復插入

INSERT INTO test_wal(val) VALUES('first insert');

-- 應該報錯,因為違反唯一約束(id列),而不是"無腦"插兩遍

說明PostgreSQL在邏輯層也有冪等保護,比如:

  • 主鍵/唯一約束
  • page LSN校驗
  • XID(事務ID)檢測

5. 注意事項和補充

  • FPW(Full Page Writes)必須打開,否則遇到partial write會導致崩潰后無法恢復。
  • 極端情況下,日志丟失(比如WAL損壞)仍然會導致恢復失敗,因此建議使用流復制+歸檔備份雙保險。
  • WAL日志管理工具(如pg_waldump)可以輔助查看日志內容,幫助理解。

示例:

pg_waldump /tmp/pgwaltest/pg_wal/

可以看到諸如:

rmgr: Heap??????? len (rec/tot):? 54/ 54, tx: 490, lsn: 0/01500280, desc: INSERT off 2

顯示了一個Heap表上的insert動作及其LSN。

總結

  • PostgreSQL WAL重放過程是嚴格冪等的。
  • 物理日志天然冪等,邏輯日志依賴于Page LSN機制保證冪等。
  • 實現細節涵蓋了page級別和事務級別的雙重校驗。
  • 實驗驗證了冪等機制的有效性。

PostgreSQL通過這些設計,確保即使在最壞情況下崩潰恢復,也能保證數據一致性和正確性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80694.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80694.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80694.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git提交規范記錄,常見的提交類型及模板、示例

Git提交規范是一種約定俗成的提交信息編寫標準&#xff0c;旨在使代碼倉庫的提交歷史更加清晰、可讀和有組織。以下是常見的Git提交類型及其對應的提交模板&#xff1a; 提交信息的基本結構 一個標準的Git提交信息通常包含以下三個主要部分&#xff1a; Header?&#xff1a;描…

FastAPI系列06:FastAPI響應(Response)

FastAPI響應&#xff08;Response&#xff09; 1、Response入門2、Response基本操作設置響應體&#xff08;返回數據&#xff09;設置狀態碼設置響應頭設置 Cookies 3、響應模型 response_model4、響應類型 response_classResponse派生類自定義response_class 在“FastAPI系列0…

每日一題(小白)模擬娛樂篇33

首先&#xff0c;理解題意是十分重要的&#xff0c;我們是要求最短路徑&#xff0c;這道題可以用dfs&#xff0c;但是題目給出的數據是有規律的&#xff0c;我們可以嘗試模擬的過程使用簡單的方法做出來。每隔w數字就會向下轉向&#xff0c;就比如題目上示例的w6&#xff0c;無…

哈希封裝unordered_map和unordered_set的模擬實現

文章目錄 &#xff08;一&#xff09;認識unordered_map和unordered_set&#xff08;二&#xff09;模擬實現unordered_map和unordered_set2.1 實現出復用哈希表的框架2.2 迭代器iterator的實現思路分析2.3 unordered_map支持[] &#xff08;三&#xff09;結束語 &#xff08;…

Java學習-Java基礎

1.重寫與重載的區別 重寫發生在父子類之間,重載發生在同類之間構造方法不能重寫,只能重載重寫的方法返回值,參數列表,方法名必須相同重載的方法名相同,參數列表必須不同重寫的方法的訪問權限不能比父類方法的訪問權限更低 2.接口和抽象類的區別 接口是interface,抽象類是abs…

BG開發者日志0427:故事的起點

1、4月26日晚上&#xff0c;BG項目的gameplay部分開發完畢&#xff0c;后續是細節以及試玩版優化。 開發重心轉移到story部分&#xff0c;目前剛開始&#xff0c; 確切地說以前是長期擱置狀態&#xff0c;因為過去的四個月中gameplay部分優先開發。 --- 2、BG這個項目的起點…

頭歌實訓之游標觸發器

&#x1f31f; 各位看官好&#xff0c;我是maomi_9526&#xff01; &#x1f30d; 種一棵樹最好是十年前&#xff0c;其次是現在&#xff01; &#x1f680; 今天來學習C語言的相關知識。 &#x1f44d; 如果覺得這篇文章有幫助&#xff0c;歡迎您一鍵三連&#xff0c;分享給更…

【深度學習】多頭注意力機制的實現|pytorch

博主簡介&#xff1a;努力學習的22級計算機科學與技術本科生一枚&#x1f338;博主主頁&#xff1a; Yaoyao2024往期回顧&#xff1a;【深度學習】注意力機制| 基于“上下文”進行編碼,用更聰明的矩陣乘法替代笨重的全連接每日一言&#x1f33c;: 路漫漫其修遠兮&#xff0c;吾…

java16

1.API續集 可以導入別人寫好的clone的jar包 注意&#xff1a;方法要有調用者&#xff0c;如果調用者是null就會報錯 2.如何導入別人寫好的jar包 復制jar包然后粘貼在lib里面&#xff0c;然后右鍵點擊jar包再點擊下面的add 3.關于打印java中的引用數據類型

PostgreSQL的擴展 credcheck

PostgreSQL的擴展 credcheck credcheck 是 PostgreSQL 的一個安全擴展&#xff0c;專門用于強制實施密碼策略和憑證檢查&#xff0c;特別適合需要符合安全合規要求的數據庫環境。 一、擴展概述 1. 主要功能 強制密碼復雜度要求防止使用常見弱密碼密碼過期策略實施密碼重復使…

MyBatis中的@Param注解-如何傳入多個不同類型的參數

mybatis中參數識別規則 默認情況下,MyBatis 會按照參數位置自動分配名稱:param1, param2, param3, ...或者 arg0, arg1。 // Mapper 接口方法 User getUserByIdAndName(Integer id, String name); 以上接口在XML中只能通過param1或者arg0這樣的方式來引用,可讀性差。 &l…

DIFY教程第一集:安裝Dify配置環境

一、Dify的介紹 https://dify.ai/ Dify 是一款創新的智能生活助手應用&#xff0c;旨在為您提供便捷、高效的服務。通過人工智能技術&#xff0c; Dify 可以實現語音 助手、智能家居控制、日程管理等功能&#xff0c;助您輕松應對生活瑣事&#xff0c;享受智慧生活。簡約的…

5、Rag基礎:RAG 專題

RAG 簡介 什么是檢索增強生成? 檢索增強生成(RAG)是指對大型語言模型輸出進行優化,使其能夠在生成響應之前引用訓練數據來源之外的權威知識庫。大型語言模型(LLM)用海量數據進行訓練,使用數十億個參數為回答問題、翻譯語言和完成句子等任務生成原始輸出。在 LLM 本就強…

GAMES202-高質量實時渲染(homework1)

目錄 Homework1shadow MapPCF(Percentage Closer Filter)PCSS(Percentage Closer Soft Shadow) GitHub主頁&#xff1a;https://github.com/sdpyy1 作業實現:https://github.com/sdpyy1/CppLearn/tree/main/games202 Homework1 shadow Map 首先需要完成MVP矩陣的構造&#xf…

JDK(Ubuntu 18.04.6 LTS)安裝筆記

一、前言 本文與【MySQL 8&#xff08;Ubuntu 18.04.6 LTS&#xff09;安裝筆記】同批次&#xff1a;先搭建數據庫&#xff0c;再安裝JDK&#xff0c;后面肯定就是部署Web應用&#xff1a;典型的單機部署。“麻雀雖小五臟俱全”&#xff0c;善始善終&#xff0c;還是記下來吧。…

軟件測試之接口測試常見面試題

一、什么是(軟件)接口測試? 接口測試&#xff1a;是測試系統組件間接口的一種測試方法 接口測試的重點&#xff1a;檢查數據的交換&#xff0c;數據傳遞的正確性&#xff0c;以及接口間的邏輯依賴關系 接口測試的意義&#xff1a;在較早期開展&#xff0c;在軟件開發的同時…

Lua 第11部分 小插曲:出現頻率最高的單詞

在本章中&#xff0c;我們要開發一個讀取并輸出一段文本中出現頻率最高的單詞的程序。像之前的小插曲一樣&#xff0c;本章的程序也十分簡單但是也使用了諸如迭代器和匿名函數這樣的高級特性。 該程序的主要數據結構是一個記錄文本中出現的每一個單詞及其出現次數之間關系的表。…

軟件項目進度管理活動詳解

目錄 1. 活動定義&#xff08;Activity Definition&#xff09; 2. 活動排序&#xff08;Activity Sequencing&#xff09; 3. 活動資源估算&#xff08;Activity Resource Estimating&#xff09; 4. 活動歷時估算&#xff08;Activity Duration Estimating&#xff09; …

docker 國內源和常用命令

Ubuntu | Docker Docs 參考docker官方安裝docker # Add Dockers official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt…

身份與訪問管理(IAM):零信任架構下的認證授權技術與實戰

身份與訪問管理&#xff08;IAM&#xff09;&#xff1a;零信任架構下的認證授權技術與實戰 在網絡安全防御體系中&#xff0c;身份與訪問管理&#xff08;Identity and Access Management, IAM&#xff09;是守護數字資產的“數字門禁系統”。隨著遠程辦公和多云架構的普及&a…