PostgreSQL事務實現


事務簡介

  • 事務管理器:有限狀態機
    • 日志管理器
      • CLOG:事務的執行結果
      • XLOG:undo/redo日志
    • 鎖管理器:實現並發控制,讀階段采用MVCC,寫階段采用鎖控制實現不同的隔離級別

PostgreSQL為每條事務創建一個postgre進程,並發執行事務。采用分層的機制執行事務,上層事務塊和底層事務。上層事務塊是用戶眼中的事務,用於控制事務執行的狀態;底層事務是事務中的每條語句,可以改變上層事務塊的狀態。

上層事務塊

每個postgre進程只有一個事務塊,上層事務塊記錄着本次事務執行過程中的各個狀態。

typedef enum TBlockState
{
	/* not-in-transaction-block states */
	TBLOCK_DEFAULT,				/* idle */
	TBLOCK_STARTED,				/* 執行簡單查詢事務 */

	/* transaction block states */
	TBLOCK_BEGIN,				/* 遇見事務開始BEGIN */
	TBLOCK_INPROGRESS,			/* 事務正在執行中 */
	TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */
	TBLOCK_END,					/* 遇見事務結束COMMIT/END的時候設置 */
	TBLOCK_ABORT,				/* 事務出錯,等待ROLLBACK */
	TBLOCK_ABORT_END,			/* 事務出錯,收到ROLLBACK */
	TBLOCK_ABORT_PENDING,		/* 事務處理中,接收到ROLLBACK */
	TBLOCK_PREPARE,				/* 事務處理中,收到PREPARE(分布式事務) */

	/* subtransaction states */
	TBLOCK_SUBBEGIN,			/* starting a subtransaction */
	TBLOCK_SUBINPROGRESS,		/* live subtransaction */
	TBLOCK_SUBRELEASE,			/* RELEASE received */
	TBLOCK_SUBCOMMIT,			/* COMMIT received while TBLOCK_SUBINPROGRESS */
	TBLOCK_SUBABORT,			/* failed subxact, awaiting ROLLBACK */
	TBLOCK_SUBABORT_END,		/* failed subxact, ROLLBACK received */
	TBLOCK_SUBABORT_PENDING,	/* live subxact, ROLLBACK received */
	TBLOCK_SUBRESTART,			/* live subxact, ROLLBACK TO received */
	TBLOCK_SUBABORT_RESTART		/* failed subxact, ROLLBACK TO received */
} TBlockState;

常見的事務塊狀態轉換圖
image

  • startTransactionCommand:事務塊中每條語句執行前都會調用。
  • commitTransactionCommand:事務塊中每條語句執行結束都會調用
  • abortCurrentTransaction:事務塊中語句執行錯誤,在調用點調用
  • BeginTransactionBlock:遇見BEGIN命令調用,狀態變為TBLOCK_BEGIN
  • EndTransactionBlock:遇見END調用,可能成功提交,也可能回滾
  • AbortTransactionBlock:遇見ABORT指令調用

底層事務

底層事務是需要執行的每條命令,負責處理資源和鎖的獲取和釋放,信號的處理,日志記錄等等

typedef enum TransState
{
	TRANS_DEFAULT,				/* idle */
	TRANS_START,				/* transaction starting */
	TRANS_INPROGRESS,			/* inside a valid transaction */
	TRANS_COMMIT,				/* commit in progress */
	TRANS_ABORT,				/* abort in progress */
	TRANS_PREPARE				/* prepare in progress */
} TransState;

主要有四個函數:

  • StartTransaction:由BEGIN的startTransactionCommand調用,調用結束后事務塊狀態為TBLOCK_STARTED
  • CommitTransaction:由END的commitTransactionCommand調用,提交事務
  • AbortTransaction和CleanupTransaction:釋放資源,恢復默認狀態

分布式事務

PostgreSQL提供了分布式事務中的,兩階段提交的接口

並發控制

PostgreSQL采用MVCC的方式進行並發控制,每個事務看到的是一段時間前的數據快照。同時,MVCC並不能夠解決所有問題,所以也提供了行級和表級的鎖。

標准的事務隔離級別有4個,而PostgreSQL只實現了讀已提交和可串行化。

PostgreSQL實現了8種鎖(可怕)

image

太多了,就記住幾個吧。

  • 行共享鎖:select for update/for share
  • 表共享鎖:select
  • 行排他鎖:insert/update/delete
  • 表排他鎖:drop

加鎖的對象

    • 表鎖
    • 會話鎖
    • 擴展鎖:新增表空間
  • 頁:對索引頁面
  • 元組:
  • 事務:

死鎖處理

image

  • postgresql檢測出最后一個等待的殺掉,oracle是第一個等待的殺掉
  • 死鎖檢測算法(等待圖)

MVCC

關鍵詞:

  • 基於事務ID
  • 行級多版本
  • 無回滾段,行內存儲
    • 一次UPDATE,產生記錄兩個版本
    • 兩個版本都存在頁面內部
typedef struct HeapTupleFields
{
	TransactionId t_xmin;		/* Insert,Update事務 */
	TransactionId t_xmax;		/* Delete,Update,Row Locks事務ID */

	union
	{
		CommandId	t_cid;		/* 操作ID */
		TransactionId t_xvac;	/* old-style VACUUM FULL xact ID */
	}			t_field3;
} HeapTupleFields;

cmin:插入該元組的命令在插入事務中的命令標識(從0開始累加)
cmax:刪除該元組的命令在插入事務中的命令標識(從0開始累加)
ctid:相當於rowid , <數據塊ID,偏移量>
XID:事務ID
Xid_snapshot:當前系統中未提交的事務
CLOG:事務狀態日志(已提交的日志)

隔離級別

  1. RC:讀已提交
    1. 兩個事務可以並發更新同一行
    2. 一個事務更新,一個事務刪除同一行,刪除操作會上鎖
  2. RR:讀未提交,其實是snapshot isolation,(沖突狀態會回滾)
  3. 可串行化:serialize snapshot isolation,比標准可串行化要高,通過加內存中的意向鎖實現,不允許預加鎖的數據被其他事務變更

數據可見性判斷

  1. 記錄的頭部XID信息比當前事務更早(rr和ssi有這個要求,read commited沒有這個要求,讀已經提交可以讀未來的事務!!)
  2. 記錄頭部的XID信息不在當前的XID_snapshot中,(記錄上的事務狀態不是未提交的事務)
  3. 記錄頭部的XID信息在CLOG中代表已提交。
  • MVCC需要判斷該行數據在這個事務中的有效性,可見性,可更新性(需要鎖的幫助才能正確執行隔離級別)
  • 判斷條件:若xmin等於當前事務ID,則包含所有xmax=0(未被刪除)的元組。
    若與xmin相等的事務ID對應的事務已經被提交,則包含所有xmax=0或xmax為當前事務ID的元組。
  • 實現概要
    • 對讀不用加鎖,對寫加鎖(只阻塞寫),事務結束對比是否沖突

多行數據需要過期版本回收

  1. 頁面級:頁面訪問時回收
  2. 表級/系統級: autovacuum; vacuum

日志

  1. pg_log:數據庫活動日志(也就是數據庫的操作日志);
  2. pg_xlog:事務日志,記錄事務的執行過程,redo日志
  3. pg_clog:事務狀態日志(pg_clog是pg_xlog的輔助日志),記錄事務的結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM