【PostgreSQL的CLOG解析】

image.png

同樣還是這張圖,之前發過shared_buffer和os cache、wal buffer和work mem的文章,今天的主題是圖中的clog,即 commit log,PostgreSQL10之前放在數據庫目錄的pg_clog下面。PostgreSQL10之后修更名為xact,數據目錄變更為pg_xact下面,表現形式是一些物理文件。

image.png


PostgreSQL為什么要使用clog呢,眾所周知,PostgreSQL有著獨特的MVCC機制,由于其多版本的特性,
在進行可見性判斷時,需要獲取事務的狀態,即元組中 t_xmin 和 t_xmax 的狀態,需要clog來記錄事務的狀態,從而判斷其可見性,內存里的訪問遠遠快于磁盤讀寫,因此PostgreSQL的很多機制都是運行時候在內存,然后定期持久化到磁盤。因此clog也有一塊內存區域便于高效訪問,即clog buffers,它也屬于共享內存的這部分,平時更新clog是內存中進行的,然后滿足條件后會調用pg_fsync刷數據到磁盤上的clog文件,或者等待checkpoint刷數據。數據庫啟動時會從磁盤的pg_xact目錄下讀取事務狀態加載到clog buffers,并且運行過程中,vacuum會定時將不再使用的clog文件清理。

關于clog buffers 的大小,可以在 src/backend/access/transam/clog.c里看到相關定義。

image.png

所以clog buffers 占用的頁的個數是NBuffers / 512,最大為128個頁,最小為4個頁,這里的NBuffers 在之前wal buffer這篇文章已經說過,它和shared_buffers的關系,兩者計算的字節數是一致的,感興趣可以去看下 (PostgreSQL的wal_buffers - 墨天輪)。
因此,這里clog buffers的大小可以理解為 shared_buffers的1/512。

PostgreSQL中通過clog來存儲事務的狀態。所以,當在Postgresql中如果想要取消一個執行了很長時間的事務,基本上是瞬間完成的,而不是像Oracle中一樣需要等到undo表空間中內容回滾完,因為PostgreSQL里只需要將事務的狀態由IN_PROGRESS修改為ABORTED即可。

PG中,事務號最多占用32位,有三個是比較特殊的,在access/xlogdefs.h下可以看到,這里的BootstrapTransactionId是用于“bootstrap”操作的XID,FrozenTransactionId用于非常老的元組。FirstNormalTransactionId是第一個“正常”的事務id。

image.png

一、事務狀態

在clog.h里定義了需要提交日志clog來記錄事務的狀態,從而判斷其可見性,在PostgreSQL里總共有四種事務狀態。分別是:IN_PROGRESS、COMMITED、ABORTED和SUB_COMMITED。例如事務正在運行中,那么它的狀態就是IN_PROGRESS。全部是0是初始狀態,SUB_COMMITTED狀態表示已提交的子事務,其父事務尚未提交或中止。每個狀態只需要兩位(2 bit)就可以表示。

image.png

二、clog文件里事務id和狀態信息的空間占用

對于上述提到的四種狀態,可以用2 bit來表示。因此四個事務的狀態就占用了8 bit 即一個字節。
在src/backend/access/transam/clog.c里一樣可以找到關于這塊空間占用的定義。

image.png

CLOG_BITS_PER_XACT:每個事務占用幾個 bit(默認為2,因為4種狀態用2bit就可以完全表示)
CLOG_XACTS_PER_BYTE :每個字節可以存幾個事務的狀態(默認為4,因為1bytes=8bit,1個事務狀態需要占用2bit)
CLOG_XACTS_PER_PAGE:每個頁可以存幾個事務的狀態(8KB*4=32K=2^15)
CLOG_XACT_BITMASK:位掩碼

三、如何根據事務ID查看在clog日志里的事務的狀態

在PostgreSQL中,事務id并不是在事務開始時就會被真正分配,它會先分配一個虛擬事務號,當有數據要發生變化時才會真正分配xid,而當事務提交或回滾時,其事務狀態便會被寫入clog中。比如你顯式開啟事務,什么都不做或者只做查詢操作,commit之后,是不會消耗xid的。而當你有對數據的變更操作,則會消耗xid。

舉個例子如下,當我們執行 select txid_current();的時候,他每次也要使用一個事務號,而當我們顯式開啟事務,然后什么都不做或者只執行select操作后,commit以后,事務號是不會增加的。我測試中增加了1是因為執行了select txid_current();的原因。而當顯示事務里有對數據的變更操作,則下次執行select txid_current();的時候,事務號直接跳了兩個,減去一個select txid_current();的,剩下那個增加的事務號則是我這個insert的事務占用的。

postgres=# select txid_current();txid_current 
--------------2119
(1 row)postgres=# select txid_current();txid_current 
--------------2120
(1 row)postgres=# begin;
BEGIN
postgres=*# select 1;?column? 
----------1
(1 row)
postgres=*# commit;
COMMIT
postgres=# select txid_current();txid_current 
--------------2121
(1 row)postgres=# begin;
BEGIN
postgres=*# insert into t1 values(5);
INSERT 0 1
postgres=*# commit;
COMMIT
postgres=# select txid_current();txid_current 
--------------2123
(1 row)

在src/backend/access/transam/clog.c里同同樣也存在著事務ID存放位置的定義和計算方法,如下所示

image.png

這四個分別為

TransactionIdToPage (事務id對應在哪個CLOG頁)

計算方法為:(xid) / (TransactionId) CLOG_XACTS_PER_PAGE,這個CLOG_XACTS_PER_PAGE是第二部分看到的每個頁可以存幾個事務的狀態,它默認是2^15。因此。事務id/ (2^15)得到的就是事務id對應在哪個CLOG頁,當然,是要取整的。從0號頁開始。

TransactionIdToPgIndex(事務id對應在上面頁中的偏移量)

計算方法為:(xid) % (TransactionId) CLOG_XACTS_PER_PAGE,即事務id%(2^15)得到的是在頁里的偏移量。

TransactionIdToByte(事務id對應在上面頁中第幾個的字節)

計算方法為:TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE,這里的TransactionIdToPgIndex(xid)是剛才計算的偏移量。而CLOG_XACTS_PER_BYTE是第二部分定義的每個字節可以存幾個事務的狀態,默認是4,所以事務在頁里的偏移量/4得到的是事務id對應在頁中第幾個的字節。

TransactionIdToBIndex(事務id對應在上面字節中的哪個bit)

計算方法為:(xid) % (TransactionId) CLOG_XACTS_PER_BYTE。這里 CLOG_XACTS_PER_BYTE依舊是每個字節可以存幾個事務的狀態,默認為4,此處不用偏移量。直接用事務id%4來得到在一個byte里的哪個bit。(1byte=8bit)

這里做一個驗證,
開啟一個session

image.png

另開一個session,查看clog

image.png

計算四個值,我們該條記錄是一個新的bytes里的
事務id對應在哪個CLOG頁=2108/(2^15)=0
事務id對應在上面頁中的偏移量=2108%(2^15)=2108
事務id對應在上面頁中第幾個的字節=2108/4=527
事務id對應在上面字節中的哪個bit=2108%4=0(表示這個事務在一bytes的第一組bits)

image.png

image.png

在commit后,原本的值應該變為01,但我們查看對應的clog文件部分是00,但是這可能并不代表事務在進程中,因為所有的狀態初始值都是00,clog的數據還沒有從內存寫到磁盤。而且clog分配于共享內存的clog_buffer中,當申請新的CLOG PAGE時所有的clog_buffer都沒有刷出臟頁,才需要主動選擇一個page并調用pg_fsync刷出對應的pg_clog到磁盤中,除此之外,checkpoint會將clog buffer刷到磁盤。因此我這里為了觀察選擇使用checkpoint。

image.png

此時clog buffer刷到了磁盤,可以看到此事務的狀態是01,對照開頭的狀態,是已經提交的狀態。

image.png

上邊的例子是一個TransactionIdToByte計算為整數的,當TransactionIdToByte計算帶有小數的時候,我們只看整數取整就可以了,例如如下的例子。

image.png

image.png

15從16進制轉換成2進制為 0001 0101 ,而上邊這個2110的事務,其計算的TransactionIdToBIndex(事務id對應在上面字節中的哪個bit)=2110%4=2,所以他在第3組bit上(取值是0為第一組),為01。因此在這個bytes里,我們的三個事務都是提交的狀態。
?

image.png


等到一個byte的四組事務全部都是commited的時候,hexdump -C 0000 -s 527 -n 1查看到的值應該是55,例如下面這種大量的55,如果不是55則表示這一bytes里的四組事務,不是全部提交的,存在IN PROCESS、ABORTED或者SUB_COMMITTED的事務。

image.png

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

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

相關文章

WPF 本地化的最佳做法

WPF 本地化的最佳做法 資源文件英文資源文件 en-US.xaml中文資源文件 zh-CN.xaml 資源使用App.xaml主界面布局cs代碼 App.config輔助類語言切換操作類資源 binding 解析類 實現效果 應用程序本地化有很多種方式,選擇合適的才是最好的。這里只討論一種方式&#xff0…

pytorch單機多卡后臺運行

nohup sh ./train_chat.sh > train_chat20230814.log 2>1&參考資料 Pytorch單機多卡后臺運行的解決辦法

kafka-2.12使用記錄

kafka-2.12使用記錄 安裝kafka 2.12版本 下載安裝包 根據你的系統下載rpm /deb /zip包等等, 這里我使用的是rpm包 安裝命令 rpm -ivh kafka-2.12-1.nfs.x86_64.rpm啟動內置Zookeeper 以下命令要寫在同一行上 /opt/kafka-2.12/bin/zookeeper-server-start.sh /opt/kafka-2…

實驗二十八、三角波發生電路參數的確認

一、題目 利用 Multisim 確定圖1所示電路中各元件的參數,使輸出電壓的頻率為 500 Hz 500\,\textrm{Hz} 500Hz、幅值為 6 V 6\,\textrm{V} 6V 的三角波。 圖 1 三角波發生電路 圖1\,\,三角波發生電路 圖1三角波發生電路 2、仿真電路 A 1 \textrm A_1 A1? 采用…

深入解析 MyBatis 中的 lt;foreachgt; 標簽:優雅處理批量操作與動態 SQL

在當今的Java應用程序開發中&#xff0c;數據庫操作是一個不可或缺的部分。MyBatis作為一款頗受歡迎的持久層框架&#xff0c;為我們提供了一種優雅而高效的方式來管理數據庫操作。在MyBatis的眾多特性中&#xff0c;<foreach>標簽無疑是一個強大的工具&#xff0c;它使得…

sift-1M數據集的讀取及ES插入數據

sift是檢查ann近鄰召回率的標準數據集,ann可以選擇faiss,milvus等庫或者方法;sift數據分為query和base,以及label(groundtruth)數據。本文采用sift-1M進行解讀,且看如下: 1、sift-1m數據集 官方鏈接地址:Evaluation of Approximate nearest neighbors: large datase…

Java:簡單算法:冒泡排序、選擇排序、二分查找

冒泡排序 // 1、準備一個數組 int[] arr {5&#xff0c;2&#xff0c;3&#xff0c;1};//2、定義一個循環控制排幾輪 for (int i 0; i < arr.length - 1; i) { // i 0 1 2 【5&#xff0c;2&#xff0c;3&#xff0c;1】 次數 // i 0 第一輪 0 1 2 …

P4377 [USACO18OPEN] Talent Show G

P4377 [USACO18OPEN] Talent Show G [P4377 USACO18OPEN] Talent Show G - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) 文章目錄 P4377 [USACO18OPEN] Talent Show G題目題目描述輸入格式輸出格式樣例 #1樣例輸入 #1樣例輸出 #1 提示樣例解釋數據規模與約定 思路code 題目 …

onlyoffice

一、功能描述 技術實現 選型&#xff1a;minio 文件存儲服務器 onlyoffice 文檔編輯器 選項特征&#xff1a;免費&#xff0c;支持私有化部署&#xff0c;不依賴第三方網絡接口 Podman是RedHat開發的一個用戶友好的容器調度器&#xff0c;是一種開源的Linux原生工具&#x…

「網絡」網絡安全必須知道的19個知識分享

一、防火墻&#xff08;Firewall&#xff09; 定義&#xff1a;都知道防火墻是干什么用的&#xff0c;但我覺得需要特別提醒一下&#xff0c;防火墻抵御的是外部的攻擊&#xff0c;并不能對內部的病毒 ( 如ARP病毒 ) 或攻擊沒什么太大作用。 功能 : 防火墻的功能主要是兩個網…

Vue2-收集表單數據、過濾器、內置指令與自定義指令、Vue生命周期

&#x1f954;&#xff1a;我徒越萬重山 千帆過 萬木自逢春 更多Vue知識請點擊——Vue.js VUE2-Day4 收集表單數據1、不同標簽的value屬性2、v-model的三個修飾符 過濾器內置指令與自定義指令1、內置指令2、自定義指令定義語法&#xff08;1&#xff09;函數式&#xff08;2&am…

文獻綜述|NLP領域后門攻擊、檢測與防御

前言&#xff1a;在信息安全中后門攻擊&#xff08;Backdoor Attack&#xff09;是指繞過安全控制而獲取對程序或系統訪問權的方法。而隨著深度學習以及各種神經網絡模型的廣泛應用&#xff0c;神經網絡中存在的后門問題也引起了研究人員的廣泛關注。神經網絡后門攻擊就是使網絡…

Android AOSP源碼編譯——AOSP整編(二)

切換到源碼目錄下執行下面命令 1、初始化環境 . build/envsetup.sh //清除緩存 make clobber2、選擇編譯目標 lunchAOSP 預制了很多 Product。這里為了簡單我們先不用真機&#xff0c;而是選擇模擬器的方式&#xff0c;對于 x86_64 模擬器&#xff0c;我們選擇的是 aosp_x86…

redisson配置類---SpringBoot集成、redis單機和集群模式配置

1項目配置文件&#xff1a; 1.1&#xff1a;pom.xml <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.7</version></dependency> 1.2 application.yml配置…

深度學習筆記(kaggle課程《Intro to Deep Learning》)

一、什么是深度學習&#xff1f; 深度學習是一種機器學習方法&#xff0c;通過構建和訓練深層神經網絡來處理和理解數據。它模仿人腦神經系統的工作方式&#xff0c;通過多層次的神經網絡結構來學習和提取數據的特征。深度學習在圖像識別、語音識別、自然語言處理等領域取得了…

Opencv將數據保存到xml、yaml / 從xml、yaml讀取數據

Opencv將數據保存到xml、yaml / 從xml、yaml讀取數據 Opencv提供了讀寫xml、yaml的類實現&#xff1a; 本文重點參考&#xff1a;https://blog.csdn.net/cd_yourheart/article/details/122705776?spm1001.2014.3001.5506&#xff0c;并將給出文件讀寫的具體使用實例。 1. 官…

C++多線程場景中的變量提前釋放導致棧內存異常

多線程場景中的棧內存異常 在子線程中嘗試使用當前函數的資源&#xff0c;是非常危險的&#xff0c;但是C支持這么做。因此C這么做可能會造成棧內存異常。 正常代碼 #include <iostream> #include <thread> #include <windows.h>// 線程函數&#xff0c;用…

Fast-Newman算法和louvain算法

fast-newman算法 fast-newman算法是一種用于社區發現的算法。它是基于newman算法的改進版本&#xff0c;旨在提高算法的運行速度和效率。fast-newman算法通過將網絡劃分為多個子圖&#xff0c;并在每個子圖上進行社區劃分&#xff0c;然后再將子圖合并&#xff0c;最終得到整個…

【分布式存儲】數據存儲和檢索~LSM

在數據庫領域&#xff0c;B樹擁有無可撼動的地位&#xff0c;但是B樹的缺點就是在寫多讀少的場景下&#xff0c;需要進行大量隨機的磁盤IO讀寫&#xff0c;而這個性能是最差的。并且在刪除和添加數據的時候&#xff0c;會造成整個樹進行遞歸的合并、分裂&#xff0c;數據在磁盤…

【JVM】類裝載的執行過程

文章目錄 類裝載的執行過程1.加載2.驗證3.準備4.解析5.初始化6.使用7.卸載 類裝載的執行過程 類裝載總共分為7個過程&#xff0c;分別是 加載&#xff0c;驗證&#xff0c;準備、解析、初始化、使用、卸載 1.加載 將類的字節碼文件加載到內存(元空間&#xff09;中。這一步會…