PostgreSQL MVCC可見性判斷

1、知識準備

1)Tuple格式頭HeapTupleHeaderData

typedef struct HeapTupleFields{
    TransactionId t_xmin;   /* inserting xact ID */
    TransactionId t_xmax;   /* deleting or locking xact ID */
    union{
        CommandId t_cid;   /* inserting or deleting command ID, or both */
        TransactionId t_xvac; /* VACUUM FULL xact ID */
    }t_field3;
}HeapTupleFields;

其中:

t_xmin:存儲的是產生這個元組的事務ID,可能是insert或者update語句

t_xmax:存儲的是刪除或者鎖定這個元組的事務ID

t_cid :包含cmin和cmax兩個字段,分別存儲創建這個元組的Command ID和刪除這個元組的Command ID

t_xvac:存儲的是VACUUM FULL 命令的事務ID

PostgreSQL主要就是通過t_xmin,t_xmax,cmin和cmax,ctid,t_infomask來唯一定義一個元組(t_xmin,t_xmax,cmin和cmax,ctid實際上也是一個表的隱藏的標記字段)。

2)Clog

PostgreSQL 在 CLOG 中維護事務的狀態,持久化存儲在 pg_xact 目錄下,爲了訪問高效,會在內存中維護一塊共享內存用於緩存 CLOG 的內容。

PG定義有四種事務狀態:

#define TRANSACTION_STATUS_IN_PROGRESS 0x00
#define TRANSACTION_STATUS_COMMITTED 0x01
#define TRANSACTION_STATUS_ABORTED 0x02
#define TRANSACTION_STATUS_SUB_COMMITTED 0x03

Clog文件以頁爲單位。數組下標是事務ID,參考TransactionIdGetStatus這個函數。數組內容是事務狀態,每個事務狀態佔用2bit即可。一個頁面8K,可以存儲8K*8/2=32K個事務狀態。Clog buffer大小爲Min(128, Max(4, NBuffers / 512)),初始化函數爲CLOGShmemInit。啓動時會從pg_xact讀取事務狀態加載到內存。系統運行過程中,vacuum會定時將不再使用的clog文件清理。

3)Hint

在進行可見性判斷時,需要獲取事務的狀態,即元組中 t_xmin 和 t_xmax 的狀態,這些事務狀態保存在 CLOG 中,爲加速獲取事務狀態的過程,PostgreSQL 引入了 Hint Bits。

所有 Hint Bits,就是把事務狀態直接記錄在元組頭中(HeapTupleHeaderData),避免頻繁訪問 CLOG,元組頭中對應的標識位如下:tuple->t_infomask

#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */
#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
#define HEAP_XMIN_FROZEN (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)
#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
#define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */

PostgreSQL 並不會在事務提交或者回滾時主動更新元組上的 Hint Bits,而是等到訪問該元組並進行可見性判斷時,如果發現 Hint Bits 沒有設置,則從 CLOG 中讀取並設置,否則直接讀取 Hint Bits 的值。判斷可見性過程中設置 Hint Bits 的函數入口爲 SetHintBits。這裏的訪問可能是 VACUUM,DML 或者 SELECT。

因此,Hint Bits 可以理解爲是事務狀態在元組頭上的一份緩存。

4)Hint與日誌

在開啓 checksum 或者 GUC 參數 wal_log_hints 爲 true 的情況下,如果 checkpoint 後第一次使頁面 dirty 的操作是更新 Hint Bits,則會產生一條 WAL 日誌,將當前頁面寫入 WAL 日誌中(即 Full Page Image),避免產生部分寫,導致數據 checksum 異常。注意,以上寫 Full Page Image 日誌的行爲與是否開啓 full_page_writes 沒有關係。因此,在開啓 checksum 或者 GUC 參數 wal_log_hints 爲 true 時,即便執行 SELECT,也可能更改頁面的 Hint Bits,從而導致產生 WAL 日誌,這會在一定程度上增加 WAL 日誌佔用的存儲空間。

2快照判斷

 

判斷一個事務是否在快照,即針對這個快照是否還在in progress:

1)大於等於snap->xmax:未來事務,不可見

2)小於snap->xmin:已結束事務,可見

3)[snap->xmin,snap->xmax):查看CLOG。Commit狀態:可見;in progress和abort狀態:不可見

3MVCC判斷可見性

 

可見性判斷規則可歸納爲:

/* t_xmin status = ABORTED */
Rule 1: IF t_xmin status is 'ABORTED' THEN
            RETURN 'Invisible'
        END IF
/* t_xmin status = IN_PROGRESS */
        IF t_xmin status is 'IN_PROGRESS' THEN
            IF t_xmin = current_txid THEN
Rule 2:         IF t_xmax = INVALID THEN
                    RETURN 'Visible'
Rule 3:         ELSE  /* this tuple has been deleted or updated by the current transaction itself. */
                    RETURN 'Invisible'
                END IF
Rule 4:     ELSE   /* t_xmin ≠ current_txid */
                RETURN 'Invisible'
            END IF
         END IF
/* t_xmin status = COMMITTED */
         IF t_xmin status is 'COMMITTED' THEN
Rule 5:     IF t_xmin is active in the obtained transaction snapshot THEN
                RETURN 'Invisible'
Rule 6:     ELSE IF t_xmax = INVALID OR status of t_xmax is 'ABORTED' THEN
                RETURN 'Visible'
            ELSE IF t_xmax status is 'IN_PROGRESS' THEN
Rule 7:         IF t_xmax =  current_txid THEN
                    RETURN 'Invisible'
Rule 8:         ELSE  /* t_xmax ≠ current_txid */
                    RETURN 'Visible'
                END IF
            ELSE IF t_xmax status is 'COMMITTED' THEN
Rule 9:         IF t_xmax is active in the obtained transaction snapshot THEN
                    RETURN 'Visible'
Rule 10:        ELSE
                    RETURN 'Invisible'
                END IF
            END IF
        END IF

 

4參考

https://yq.aliyun.com/articles/675939

http://blog.itpub.net/6906/viewspace-2562652/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章