PostgreSQL 事務模型介紹

fiona8953發表於2016-08-02

PostgreSQL有自己的事務實現模型。總體上分為三層:top layer, middle layer和bottom layer。

1. Top Layer

Top Layer主要由使用者控制,對使用者可見。這一層的事務,主要由使用者來決定事務的發起與結束。事務生命週期由使用者控制,是high-level的。

也就是通常所說的事務塊,transaction block。當使用者發起:BEGIN, COMMIT, ROLLBACK, SAVEPOINT, ROLLBACK TO or RELEASE等命令時,

PG的traffic cop會將這些call重新轉發到Top Layer routine中,相對應的方法如下:
BeginTransactionBlock
EndTransactionBlock
UserAbortTransactionBlock
DefineSavepoint
RollbackToSavepoint
ReleaseSavepoint

 

2.Middle Layer

這一層基本上是語句級別的。對使用者不可見,也就是說使用者無法控制具體生命週期。這一層的處理是跟語句相對應的。由postgres.c處理,相對應的方法如下:

StartTransactionCommand
CommitTransactionCommand
AbortCurrentTransaction

 

3.Bottom Layer

這是最低層的事務原子性的實現,是row-level級別的。是真正意義上的事務實現,以及巢狀事務處理等。

相對應的方法如下:

StartTransaction
CommitTransaction
AbortTransaction
CleanupTransaction
StartSubTransaction
CommitSubTransaction
AbortSubTransaction
CleanupSubTransaction

 

從上面三層模型,可以看出PG事務管理粒度由粗到細。呼叫由中層向底層呼叫。另外如果有使用者級別的事務控制,如出現“BEGIN”等,則被postgres.c轉發到top layer中。

假設下面一個案例:

1)        BEGIN
2)        SELECT * FROM foo
3)        INSERT INTO foo VALUES (...)
4)        COMMIT

那麼相應的呼叫方法呼叫循序如下:

     /  StartTransactionCommand;
    /       StartTransaction;
1) <        ProcessUtility;             << BEGIN
    \       BeginTransactionBlock;
     \  CommitTransactionCommand;

    /   StartTransactionCommand;
2) /        ProcessQuery;               << SELECT ...
   \        CommitTransactionCommand;
    \       CommandCounterIncrement;

    /   StartTransactionCommand;
3) /        ProcessQuery;               << INSERT ...
   \        CommitTransactionCommand;
    \       CommandCounterIncrement;

     /  StartTransactionCommand;
    /   ProcessUtility;                 << COMMIT
4) <            EndTransactionBlock;
    \   CommitTransactionCommand;
     \      CommitTransaction;

 

在第一步中,使用者定義的事務邊界開始,也是此事務的生命週期起點。

首先,”BEGIN”也是作為一個命令語句的,因此本身這一步也是需要middle layer中的方法呼叫將其包圍起來。

接著起動low-level事務,即由middle layer呼叫bottom layer的方法。StartTransaction時,會生成vxid(virtual transaction id,即backend id與local transaction id)。

判斷當前事務是否是read-only或者目前是否處於recovery狀態。事務隔離級別,事務是否非同步commit等資訊都在這裡初始化。將transState狀態設定為:TRANS_INPROCESS。

因為有“BEGIN”命令語句,所以是top layer的。因此又被轉到BeginTransactionBlock邏輯中。開始transaction block 處理,並將事務狀態設定為:TBLOCK_START。

起transaction block和起transaction的區別在於對事務狀態的設定不一樣。

start trasaction block是將事務狀態設定為:TBLOCK_START,而一般的start transaction是將其設定為:TRANS_INPROCESS。

事務塊與事務是有區別的,在狀態上。事務塊有以下幾種狀態,是可以巢狀的:

image

而一般事務,只有以下幾種狀態,沒有巢狀:

image

另外,在原始碼定義上,用了不同的結構體來儲存。TransState,儲存low-level事務狀態。

而TBlockState儲存high-level事務狀態。從這裡也明顯可以看出,PG在事務層級上做了區分的。

image

 

在第二步中,發起select查詢。上面講過,middle layer是跟命令語句對應的。因此針對select 查詢,也是用middle layer中的方法呼叫將其包圍。

另外增加CID,用於同一事務中的MVCC可見性判斷。

 

在第三步中,發起insert操作。這一步大邏輯上基本上等同於第二步。只是在處理insert時,需要將當前的xid更新到tupler header中去。

通常涉及到insert,update,delete等操作都是跟heap緊密相關,涉及到heap的物理上tuple新增和刪除。在這一層中,PG需要為每一個DML

操作assign一個事務ID,並將此事務ID更新到tuple header中的xmin或者xmax中。從而實現MVCC。另外這一層也會增加commandID,主要用來實現同一事務中的可見性判斷。

 

在第四步中,使用者發起commit,提交事務。事務生命週期結束。這一步邏輯等同於第一步。這裡不僅需要結束top layer 的transaction block。也需要結束low-level中的事務,實現

事務原子性。另外還需要釋放資源,釋放buffer pin,釋放鎖等。

 

從上面的講解中,我們可以比較清晰的看到,PG在事務實現的大致邏輯。完整實現ACID功能。

Atomity:原子性由low-level級別實現,從StartTransaction開始,結束於CommitTransaction。

Consistency:一致性由語句級別實現,即middle layer對應。另外在tuple header 中更新的xmin,xmax,cmin,cmax為事務可見性提供判斷基礎。

Isolation:在StartTransaction時,初始化事務隔離級別。為MVCC建立snapshot時,提供基礎。

Duarability:透過CommitTransaction實現,提交事務日誌等。為資料恢復和持久化提供基礎。實現WAL(Write Ahead Log)功能。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26477398/viewspace-2122848/,如需轉載,請註明出處,否則將追究法律責任。

相關文章