PostgreSQL 事務ID環繞問題

事務ID(XID)基本概念

從Transactions and Identifiers可知:

事務 ID,例如 278394,會根據 PostgreSQL 集群內所有數據庫使用的全局計數器按順序分配給事務。此分配會在事務首次寫入數據庫時進行。這意味著編號較低的 xid 會先于編號較高的 xid 寫入。
?
事務 ID 類型 xid 為 32 位寬,每 40 億次事務繞回一次。每次繞回時,都會增加一個 32 位的紀元 (epoch)。此外,還有一個 64 位類型 xid8,它包含這個紀元,因此在安裝的生命周期內不會繞回;它可以通過強制類型轉換轉換為 xid。xid 是 PostgreSQL MVCC 并發機制和流復制的基礎

交易ID和快照信息函數參見這里。

日常清理(VACUUM)中的凍結操作

PostgreSQL 數據庫需要定期維護,稱為清理(vacuum)。其中除更新統計信息,回收空間外,一項重要的任務就是防止由于事務 ID 回繞或多事務 ID 回繞而丟失非常舊的數據。

從Preventing Transaction ID Wraparound Failures可知:

PostgreSQL 的 MVCC 事務語義依賴于能夠比較事務 ID (XID) 編號:如果行版本的插入 XID 大于當前事務的 XID,則該行版本“位于未來”,對當前事務不可見。但由于事務 ID 的大小有限(32 位),因此長期運行的集群(超過 40 億個事務)將遭遇事務 ID 回繞:XID 計數器會回繞為零,過去的事務會突然變成未來的事務 — — 這意味著它們的輸出變得不可見。簡而言之,就是災難性的數據丟失。(實際上數據仍然存在,但如果您無法獲取數據,這也只是些安慰。)為了避免這種情況,有必要至少每 20 億個事務清理一次每個數據庫中的每個表。

為何是至少每 20 億個事務清理一次,這是由autovacuum_freeze_max_age參數控制的:

sampledb=> show autovacuum_freeze_max_age;autovacuum_freeze_max_age
---------------------------200000000
(1 row)

20 億實際是XID取值范圍的一半,即231

定期清理能夠解決這個問題的原因是,VACUUM 會將行標記為凍結,表明這些行是由一個提交時間足夠久的事務插入的,因此插入事務的影響對所有當前和未來的事務都可見。普通 XID 使用模 232 算法進行比較。這意味著對于每個普通 XID,都有 20 億個“更舊”的 XID 和 20 億個“更新”的 XID;換句話說,普通 XID 空間是循環的,沒有端點。因此,一旦使用特定的普通 XID 創建了行版本,那么在接下來的 20 億個事務中,無論我們討論的是哪個普通 XID,該行版本都會看起來像是“過去”的。如果在超過 20 億個事務之后,該行版本仍然存在,它就會突然看起來像是未來。為了防止這種情況,PostgreSQL 保留了一個特殊的 XID,FrozenTransactionId,它不遵循普通 XID 比較規則,并且始終被認為比所有普通 XID 都舊。凍結行版本被視為插入 XID 是 FrozenTransactionId,因此無論環繞問題如何,它們對于所有正常事務都將顯示為“過去”,因此此類行版本將一直有效,直到被刪除,無論時間有多長。

所謂是循環的,沒有端點類似于下圖:

012...2^32-101...

每一個表都有系統定義的隱含列,xmin和xmax:

sampledb=> select xmin, xmax from regions limit 1;xmin | xmax
------+------5190 |    0
(1 row)

所謂凍結就是將xmin的值設為FrozenTransactionId(實際值為2),設置后xmin的值不會再被修改。

vacuum_freeze_min_age 控制 XID 值的有效期,超過該 XID 值的行才會被凍結。如果原本會被凍結的行很快會被再次修改,則增加此設置可以避免不必要的工作;但降低此設置會增加在必須再次清理表之前可以處理的事務數。

表未清理的最長時間是20億個事務數減去上次激進清理時的vacuum_freeze_min_age值。如果未清理的時間超過該時間,可能會導致數據丟失。為確保不會發生這種情況,任何可能包含XID大于配置參數autovacuum_freeze_max_age指定的未凍結行的表都會被調用自動清理。(即使禁用自動清理,也會發生這種情況。)

事務ID環繞問題是如何產生和解決的

前面已經談到了普通 XID 使用模 232 算法進行比較。這個規則就是:

如果(NextXID - xmin) % 2^32 < 2^31,則 xmin 屬于過去

PostgreSQL 將 “當前 XID ± 2^31 (≈ 20 億)” 作為 可見窗口,因此總有約20億屬于過去,20億屬于未來(中間那個|即NextXID):

<---------------- 2^31 = 2,147,483,648 ---------------->“過去”                   “未來”
-----------------------|------------------------------>可見                   不可見

先看一個屬于過去的例子。

假設xmin = 4,294,967,000,接近2^32。XID已經回繞,此時NextXID = 100。
根據算法(NextXID - xmin) % 2^32 < 2^31

NextXID = 100
xmin = 4,294,967,000
delta = (100 - 4,294,967,000) % 4,294,967,296= ( -4,294,966,900 ) % 4,294,967,296= 396

顯然,396小于2^31,因此xmin雖然接近XID的最大值,但屬于過去。

再看一個屬于未來的例子,xmin和上例相同:

NextXID = 2,147,483,700
xmin = 4,294,967,000
delta = (2,147,483,700 - 4,294,967,000) % 4,294,967,296= (-2,147,483,300) % 4,294,967,296= 2,147,483,996

此時,delta大于2^31,因此xmin屬于未來。

xmin并沒有發生變化,而此時卻被視為未來,這顯然是錯誤的。通過凍結,即將xmin置為FrozenTransactionId,即可解決事務ID環繞問題。

在源碼文件./backend/access/transam/transam.c中,可以找到此算法:

// git clone https://github.com/postgres/postgres.git 檢出源碼
/** TransactionIdPrecedes --- is id1 logically < id2?*/
bool
TransactionIdPrecedes(TransactionId id1, TransactionId id2)
{/** If either ID is a permanent XID then we can just do unsigned* comparison.  If both are normal, do a modulo-2^32 comparison.*/int32           diff;if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))return (id1 < id2);diff = (int32) (id1 - id2);return (diff < 0);
}

監控XID環繞

postgres=# SELECT datname,age(datfrozenxid) AS xid_age,2000000000 - age(datfrozenxid) AS remaining_before_wraparound
FROM pg_database;datname       | xid_age | remaining_before_wraparound
--------------------+---------+-----------------------------postgres           |    5375 |                  1999994625template1          |    5375 |                  1999994625template0          |    5375 |                  1999994625world_temperatures |    5375 |                  1999994625demo               |    5375 |                  1999994625sampledb           |    5375 |                  1999994625
(6 rows)

可以參照Transaction ID wraparound: a walk on the wild side,模擬事務ID環繞問題。

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

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

相關文章

高等數學-矩陣知識

好的&#xff0c;我們來詳細講解高等數學&#xff08;主要是線性代數部分&#xff09;中的核心矩陣知識。矩陣是線性代數的基石&#xff0c;廣泛應用于數學、物理、工程、計算機科學、經濟學等眾多領域。 一、矩陣的基本概念定義&#xff1a; 一個 m n 矩陣 (Matrix) 是一個由…

React 項目性能優化概要

應用級性能優化&#xff0c;需要結合實際需求展開分析&#xff0c;通常我們需要從以下幾個方面來考慮&#xff1a; 1. 識別性能瓶頸 識別性能瓶頸是優化的第一步&#xff0c;通過各種工具和方法找到影響性能的主要原因&#xff1a; React Profiler&#xff1a;使用 React Dev…

【web自動化】-5- fixture集中管理和項目重構

一、投標用例設計 # 定義讓前臺頁面保持自動登錄的fixture pytest.fixture() def user_driver():driver webdriver.Chrome()driver.get("http://47.107.116.139/fangwei/")driver.maximize_window()# 創建頁面類對象page ReceptionLoginPage(driver)# 通過頁面類對…

Dify工作流:爬蟲文章到AI知識庫

部署Dify 代碼拉取 git clone https://github.com/langgenius/dify.git cd dify/docker啟動容器 docker-compose up -d啟動成功準備知識庫 創建知識庫 創建一個空的知識庫要先從網址中&#xff0c;找到這個知識庫的id&#xff0c;記下后面需要用到。新建API密鑰 創建密鑰&#…

支付鑒權方案介紹

前后端交互中的鑒權是確保請求來源合法、身份可信、權限合適的關鍵手段。不同系統架構和業務類型下,使用的鑒權方式略有不同,但主要可分為以下幾類: ? 一、前后端交互常見的鑒權方式概覽 鑒權方式 優點 缺點 適用場景 Cookie + Session 簡單、成熟,服務端易控制 不適合跨域…

halcon處理灰度能量圖

使用halcon處理射線圖像&#xff0c;對高能區域和低能區域分割處理感興趣區域&#xff0c;篩選區域下的灰度值區間范圍。圖像灰度值為16位深度圖。* 讀取灰度圖像 read_image (Image, /123.tif)** 獲取圖像尺寸 get_image_size (Image, Width, Height)* 分割圖像為左右兩部分&a…

Oracle From查看彈性域設置

打開彈性與設置&#xff1a;【應用開發員->彈性域->說明性->段】打開后界面如下&#xff1a; 把光標定位到標題&#xff0c;然后點擊“手電筒”搜索名稱&#xff08;名稱就是你要查詢的那個彈性域的名稱&#xff09;我這里就是搜索“附加題頭信息”&#xff0…

git初始流程

對于一個新項目&#xff0c;從 Git 倉庫拉取 test_tool 分支并進行后續修改提交的完整流程如下&#xff1a; 一、首次拉取項目&#xff08;克隆倉庫并切換分支&#xff09;克隆遠程倉庫到本地 打開終端&#xff08;或 PyCharm 的 Terminal&#xff09;&#xff0c;進入你想存放…

emuelec模擬器 ,s905盒子樹莓派街機游戲

EmuELEC支持的盒子類型相當廣泛&#xff0c;主要包括使用以下芯片方案的機頂盒等設備&#xff1a; S905系列及其變體&#xff1a;如S905、S905D、S905L、S905M、S905X、S905X2、S905X3、S905X4、S905W、S905Y等。 S912&#xff1a;這也是EmuELEC支持的一個常見芯片方案。 S922x…

Ansible部署

Ansible部署 一、部署環境及前置操作 1、測試環境 注:主機復用原測試環境&#xff0c;主機hostname根據需求調整 硬件環境&#xff1a;N100 x86主機 Proxmox系統 軟件環境&#xff1a;Ubuntu 22.04.3 LTS 軟件版本&#xff1a;redis-7.4.0.tar.gz 主機環境&#xff1a;主機IP …

智慧教室:科技賦能,奏響個性化學習新樂章

在傳統教育模式中&#xff0c;課堂互動的局限性猶如一道無形的枷鎖&#xff0c;束縛著學生主動學習的熱情與能力。課堂上&#xff0c;往往是教師單向的知識輸出&#xff0c;僅有少數學生能獲得發言機會&#xff0c;大部分學生只能被動聆聽&#xff0c;逐漸在枯燥的學習氛圍中喪…

Android埋點實現方案深度分析

埋碼是數據驅動業務決策、產品優化、用戶行為分析的核心基礎&#xff0c;其實現方案的優劣直接影響數據的準確性、完整性、實時性、可維護性以及開發效率。 以下從多個維度對主流方案進行剖析&#xff1a; 一、核心目標與挑戰目標&#xff1a; 精準采集&#xff1a; 在用戶觸發…

萬界星空科技銅線/漆包線行業智能化MES系統解決方案

萬界星空科技針對銅線及漆包線行業開發的智能化MES系統&#xff0c;專門解決該行業原材料管理復雜、工藝控制嚴、質量追溯困難等核心痛點。該系統通過數字化手段實現生產全流程的可視化與精準控制&#xff0c;助力企業提升生產效率、降低運營成本并增強市場競爭力。一、行業專屬…

Git 完全手冊:從入門到團隊協作實戰(3)

Hello大家好&#xff01;很高興我們又見面啦&#xff01;給生活添點passion&#xff0c;開始今天的編程之路&#xff01; 我的博客&#xff1a;<但凡. 我的專欄&#xff1a;《編程之路》、《數據結構與算法之美》、《C修煉之路》、《Linux修煉&#xff1a;終端之內 洞悉真理…

使用Docker搭建SearXNG搜索引擎

1、安裝Docker# 安裝Docker https://docs.docker.com/get-docker/# 安裝Docker Compose https://docs.docker.com/compose/install/# CentOS安裝Docker https://mp.weixin.qq.com/s/nHNPbCmdQs3E5x1QBP-ueA2、安裝SearXNG詳見&#xff1a; https://docs.searxng.org/admin/inst…

基于pi/4-QPSK擴頻解擴和gardner環定時同步的通信系統matlab性能仿真

目錄 1.引言 2.算法仿真效果演示 3.數據集格式或算法參數簡介 4.算法涉及理論知識概要 4.1 π/4-QPSK 4.2 直接序列擴頻與解擴 4.3 Gardner環定時同步 5.參考文獻 6.完整算法代碼文件獲得 1.引言 π/4-QPSK是一種特殊的QPSK調制方式&#xff0c;其相鄰符號間的相位跳變…

CGA老年人能力評估師:提升老年生活質量

一、CGA老年人能力評估師是提升老年生活質量的“導航者” 老年生活質量的提升&#xff0c;始于對老年人真實需求的精準把握。CGA老年人能力評估師正是這樣一群“導航者”&#xff0c;他們運用CGA老年綜合評估系統&#xff0c;深入了解老年人在生理、心理、社會參與等方面的狀況…

開源的大語言模型(LLM)應用開發平臺Dify

概述Dify 是一個開源的大語言模型&#xff08;LLM&#xff09;應用開發平臺&#xff0c;結合了后端即服務&#xff08;Backend-as-a-Service&#xff09;和 LLMOps 的理念&#xff0c;旨在幫助開發者快速構建生產級的生成式 AI 應用。它通過直觀的界面、強大的功能和靈活的部署…

RAG(檢索增強生成)里的文檔管理

RAG&#xff08;檢索增強生成&#xff09;是結合檢索與生成式 AI 的技術框架。核心邏輯是先從外部知識庫精準檢索相關信息&#xff0c;再將其作為上下文輸入大模型生成回答。技術上依賴檢索引擎&#xff08;如向量數據庫、BM25&#xff09;、大語言模型&#xff08;如 GPT、LLa…

床上肢體康復機器人的機械結構設計cad【7張】三維圖+設計說明書

摘要 近年來&#xff0c;隨著人口老齡化問題的加重&#xff0c;常年臥床的老年人數增多&#xff0c;同時因為各種疾病的原因&#xff0c;患肢體功能障礙的人數也在增加。嚴重影響著患者的生活質量&#xff0c;同時給社會和家庭增加了很多麻煩。他們迫切希望盡快康復&#xff0c…