本文實例講述了PostgreSQL數(shù)據(jù)庫事務實現(xiàn)方法。分享給大家供大家參考,具體如下:
事務簡介
- 事務管理器:有限狀態(tài)機
- 日志管理器
- CLOG:事務的執(zhí)行結果
- XLOG:undo/redo日志
- 鎖管理器:實現(xiàn)并發(fā)控制,讀階段采用MVCC,寫階段采用鎖控制實現(xiàn)不同的隔離級別
事務是所有數(shù)據(jù)庫系統(tǒng)的一個基本概念。 一次事務的要點就是它把多個步驟捆綁成了一個單一的,不成功則成仁的操作。 其它并發(fā)的事務是看不到在這些步驟之間的中間狀態(tài)的,并且如果發(fā)生了一些問題, 導致該事務無法完成,那么所有這些步驟都完全不會影響數(shù)據(jù)庫。PostgreSQL為每條事務創(chuàng)建一個postgre進程,并發(fā)執(zhí)行事務。采用分層的機制執(zhí)行事務,上層事務塊和底層事務。上層事務塊是用戶眼中的事務,用于控制事務執(zhí)行的狀態(tài);底層事務是事務中的每條語句,可以改變上層事務塊的狀態(tài)。
上層事務塊
每個postgre進程只有一個事務塊,上層事務塊記錄著本次事務執(zhí)行過程中的各個狀態(tài)。
typedef enum TBlockState
{
/* not-in-transaction-block states */
TBLOCK_DEFAULT, /* idle */
TBLOCK_STARTED, /* 執(zhí)行簡單查詢事務 */
/* transaction block states */
TBLOCK_BEGIN, /* 遇見事務開始BEGIN */
TBLOCK_INPROGRESS, /* 事務正在執(zhí)行中 */
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;
常見的事務塊狀態(tài)轉換圖
- startTransactionCommand:事務塊中每條語句執(zhí)行前都會調(diào)用。
- commitTransactionCommand:事務塊中每條語句執(zhí)行結束都會調(diào)用
- abortCurrentTransaction:事務塊中語句執(zhí)行錯誤,在調(diào)用點調(diào)用
- BeginTransactionBlock:遇見BEGIN命令調(diào)用,狀態(tài)變?yōu)門BLOCK_BEGIN
- EndTransactionBlock:遇見END調(diào)用,可能成功提交,也可能回滾
- AbortTransactionBlock:遇見ABORT指令調(diào)用
底層事務
底層事務是需要執(zhí)行的每條命令,負責處理資源和鎖的獲取和釋放,信號的處理,日志記錄等等
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;
主要有四個函數(shù):
- StartTransaction:由BEGIN的startTransactionCommand調(diào)用,調(diào)用結束后事務塊狀態(tài)為TBLOCK_STARTED
- CommitTransaction:由END的commitTransactionCommand調(diào)用,提交事務
- AbortTransaction和CleanupTransaction:釋放資源,恢復默認狀態(tài)
分布式事務
PostgreSQL提供了分布式事務中的,兩階段提交的接口
并發(fā)控制
PostgreSQL采用MVCC的方式進行并發(fā)控制,每個事務看到的是一段時間前的數(shù)據(jù)快照。同時,MVCC并不能夠解決所有問題,所以也提供了行級和表級的鎖。
標準的事務隔離級別有4個,而PostgreSQL只實現(xiàn)了讀已提交和可串行化。
鎖
PostgreSQL實現(xiàn)了8種鎖(可怕)
太多了,就記住幾個吧。
- 行共享鎖:select for update/for share
- 表共享鎖:select
- 行排他鎖:insert/update/delete
- 表排他鎖:drop
加鎖的對象
死鎖處理
- postgresql檢測出最后一個等待的殺掉,oracle是第一個等待的殺掉
- 死鎖檢測算法(等待圖)
MVCC
關鍵詞:
- 基于事務ID
- 行級多版本
- 無回滾段,行內(nèi)存儲
- 一次UPDATE,產(chǎn)生記錄兩個版本
- 兩個版本都存在頁面內(nèi)部
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 , 數(shù)據(jù)塊ID,偏移量>
XID
:事務ID
Xid_snapshot
:當前系統(tǒng)中未提交的事務
CLOG
:事務狀態(tài)日志(已提交的日志)
隔離級別
- RC:讀已提交
- 兩個事務可以并發(fā)更新同一行
- 一個事務更新,一個事務刪除同一行,刪除操作會上鎖
- RR:讀未提交,其實是snapshot isolation,(沖突狀態(tài)會回滾)
- 可串行化:serialize snapshot isolation,比標準可串行化要高,通過加內(nèi)存中的意向鎖實現(xiàn),不允許預加鎖的數(shù)據(jù)被其他事務變更
數(shù)據(jù)可見性判斷
- 記錄的頭部XID信息比當前事務更早(rr和ssi有這個要求,read commited沒有這個要求,讀已經(jīng)提交可以讀未來的事務??!)
- 記錄頭部的XID信息不在當前的XID_snapshot中,(記錄上的事務狀態(tài)不是未提交的事務)
- 記錄頭部的XID信息在CLOG中代表已提交。
- MVCC需要判斷該行數(shù)據(jù)在這個事務中的有效性,可見性,可更新性(需要鎖的幫助才能正確執(zhí)行隔離級別)
- 判斷條件:若xmin等于當前事務ID,則包含所有xmax=0(未被刪除)的元組。
若與xmin相等的事務ID對應的事務已經(jīng)被提交,則包含所有xmax=0或xmax為當前事務ID的元組。
- 實現(xiàn)概要
- 對讀不用加鎖,對寫加鎖(只阻塞寫),事務結束對比是否沖突
多行數(shù)據(jù)需要過期版本回收
- 頁面級:頁面訪問時回收
- 表級/系統(tǒng)級: autovacuum; vacuum
日志
- pg_log:數(shù)據(jù)庫活動日志(也就是數(shù)據(jù)庫的操作日志);
- pg_xlog:事務日志,記錄事務的執(zhí)行過程,redo日志
- pg_clog:事務狀態(tài)日志(pg_clog是pg_xlog的輔助日志),記錄事務的結果。
希望本文所述對大家PostgreSQL數(shù)據(jù)庫程序設計有所幫助。
您可能感興趣的文章:- 用PostgreSQL數(shù)據(jù)庫做地理位置app應用
- Python實現(xiàn)連接postgresql數(shù)據(jù)庫的方法分析
- C# 操作PostgreSQL 數(shù)據(jù)庫的示例代碼
- 在Ubuntu中安裝Postgresql數(shù)據(jù)庫的步驟詳解
- 詳解PostgreSql數(shù)據(jù)庫對象信息及應用