PostgreSQL數(shù)據(jù)庫(kù)事務(wù)實(shí)現(xiàn)方法分析
本文實(shí)例講述了PostgreSQL數(shù)據(jù)庫(kù)事務(wù)實(shí)現(xiàn)方法。分享給大家供大家參考,具體如下:
事務(wù)簡(jiǎn)介
- 事務(wù)管理器:有限狀態(tài)機(jī)
- 日志管理器
- CLOG:事務(wù)的執(zhí)行結(jié)果
- XLOG:undo/redo日志
- 鎖管理器:實(shí)現(xiàn)并發(fā)控制,讀階段采用MVCC,寫階段采用鎖控制實(shí)現(xiàn)不同的隔離級(jí)別
- 日志管理器
事務(wù)是所有數(shù)據(jù)庫(kù)系統(tǒng)的一個(gè)基本概念。 一次事務(wù)的要點(diǎn)就是它把多個(gè)步驟捆綁成了一個(gè)單一的,不成功則成仁的操作。 其它并發(fā)的事務(wù)是看不到在這些步驟之間的中間狀態(tài)的,并且如果發(fā)生了一些問題, 導(dǎo)致該事務(wù)無法完成,那么所有這些步驟都完全不會(huì)影響數(shù)據(jù)庫(kù)。PostgreSQL為每條事務(wù)創(chuàng)建一個(gè)postgre進(jìn)程,并發(fā)執(zhí)行事務(wù)。采用分層的機(jī)制執(zhí)行事務(wù),上層事務(wù)塊和底層事務(wù)。上層事務(wù)塊是用戶眼中的事務(wù),用于控制事務(wù)執(zhí)行的狀態(tài);底層事務(wù)是事務(wù)中的每條語句,可以改變上層事務(wù)塊的狀態(tài)。
上層事務(wù)塊
每個(gè)postgre進(jìn)程只有一個(gè)事務(wù)塊,上層事務(wù)塊記錄著本次事務(wù)執(zhí)行過程中的各個(gè)狀態(tài)。
typedef enum TBlockState
{
/* not-in-transaction-block states */
TBLOCK_DEFAULT, /* idle */
TBLOCK_STARTED, /* 執(zhí)行簡(jiǎn)單查詢事務(wù) */
/* transaction block states */
TBLOCK_BEGIN, /* 遇見事務(wù)開始BEGIN */
TBLOCK_INPROGRESS, /* 事務(wù)正在執(zhí)行中 */
TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */
TBLOCK_END, /* 遇見事務(wù)結(jié)束COMMIT/END的時(shí)候設(shè)置 */
TBLOCK_ABORT, /* 事務(wù)出錯(cuò),等待ROLLBACK */
TBLOCK_ABORT_END, /* 事務(wù)出錯(cuò),收到ROLLBACK */
TBLOCK_ABORT_PENDING, /* 事務(wù)處理中,接收到ROLLBACK */
TBLOCK_PREPARE, /* 事務(wù)處理中,收到PREPARE(分布式事務(wù)) */
/* 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;
常見的事務(wù)塊狀態(tài)轉(zhuǎn)換圖

- startTransactionCommand:事務(wù)塊中每條語句執(zhí)行前都會(huì)調(diào)用。
- commitTransactionCommand:事務(wù)塊中每條語句執(zhí)行結(jié)束都會(huì)調(diào)用
- abortCurrentTransaction:事務(wù)塊中語句執(zhí)行錯(cuò)誤,在調(diào)用點(diǎn)調(diào)用
- BeginTransactionBlock:遇見BEGIN命令調(diào)用,狀態(tài)變?yōu)門BLOCK_BEGIN
- EndTransactionBlock:遇見END調(diào)用,可能成功提交,也可能回滾
- AbortTransactionBlock:遇見ABORT指令調(diào)用
底層事務(wù)
底層事務(wù)是需要執(zhí)行的每條命令,負(fù)責(zé)處理資源和鎖的獲取和釋放,信號(hào)的處理,日志記錄等等
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;
主要有四個(gè)函數(shù):
- StartTransaction:由BEGIN的startTransactionCommand調(diào)用,調(diào)用結(jié)束后事務(wù)塊狀態(tài)為TBLOCK_STARTED
- CommitTransaction:由END的commitTransactionCommand調(diào)用,提交事務(wù)
- AbortTransaction和CleanupTransaction:釋放資源,恢復(fù)默認(rèn)狀態(tài)
分布式事務(wù)
PostgreSQL提供了分布式事務(wù)中的,兩階段提交的接口
并發(fā)控制
PostgreSQL采用MVCC的方式進(jìn)行并發(fā)控制,每個(gè)事務(wù)看到的是一段時(shí)間前的數(shù)據(jù)快照。同時(shí),MVCC并不能夠解決所有問題,所以也提供了行級(jí)和表級(jí)的鎖。
標(biāo)準(zhǔn)的事務(wù)隔離級(jí)別有4個(gè),而PostgreSQL只實(shí)現(xiàn)了讀已提交和可串行化。
鎖
PostgreSQL實(shí)現(xiàn)了8種鎖(可怕)

太多了,就記住幾個(gè)吧。
- 行共享鎖:select for update/for share
- 表共享鎖:select
- 行排他鎖:insert/update/delete
- 表排他鎖:drop
加鎖的對(duì)象
- 表
- 表鎖
- 會(huì)話鎖
- 擴(kuò)展鎖:新增表空間
- 頁(yè):對(duì)索引頁(yè)面
- 元組:
- 事務(wù):
死鎖處理

- postgresql檢測(cè)出最后一個(gè)等待的殺掉,oracle是第一個(gè)等待的殺掉
- 死鎖檢測(cè)算法(等待圖)
MVCC
關(guān)鍵詞:
- 基于事務(wù)ID
- 行級(jí)多版本
- 無回滾段,行內(nèi)存儲(chǔ)
- 一次UPDATE,產(chǎn)生記錄兩個(gè)版本
- 兩個(gè)版本都存在頁(yè)面內(nèi)部
typedef struct HeapTupleFields
{
TransactionId t_xmin; /* Insert,Update事務(wù) */
TransactionId t_xmax; /* Delete,Update,Row Locks事務(wù)ID */
union
{
CommandId t_cid; /* 操作ID */
TransactionId t_xvac; /* old-style VACUUM FULL xact ID */
} t_field3;
} HeapTupleFields;
cmin:插入該元組的命令在插入事務(wù)中的命令標(biāo)識(shí)(從0開始累加)
cmax:刪除該元組的命令在插入事務(wù)中的命令標(biāo)識(shí)(從0開始累加)
ctid:相當(dāng)于rowid , <數(shù)據(jù)塊ID,偏移量>
XID:事務(wù)ID
Xid_snapshot:當(dāng)前系統(tǒng)中未提交的事務(wù)
CLOG:事務(wù)狀態(tài)日志(已提交的日志)
隔離級(jí)別
- RC:讀已提交
- 兩個(gè)事務(wù)可以并發(fā)更新同一行
- 一個(gè)事務(wù)更新,一個(gè)事務(wù)刪除同一行,刪除操作會(huì)上鎖
- RR:讀未提交,其實(shí)是snapshot isolation,(沖突狀態(tài)會(huì)回滾)
- 可串行化:serialize snapshot isolation,比標(biāo)準(zhǔn)可串行化要高,通過加內(nèi)存中的意向鎖實(shí)現(xiàn),不允許預(yù)加鎖的數(shù)據(jù)被其他事務(wù)變更
數(shù)據(jù)可見性判斷
- 記錄的頭部XID信息比當(dāng)前事務(wù)更早(rr和ssi有這個(gè)要求,read commited沒有這個(gè)要求,讀已經(jīng)提交可以讀未來的事務(wù)?。?
- 記錄頭部的XID信息不在當(dāng)前的XID_snapshot中,(記錄上的事務(wù)狀態(tài)不是未提交的事務(wù))
- 記錄頭部的XID信息在CLOG中代表已提交。
- MVCC需要判斷該行數(shù)據(jù)在這個(gè)事務(wù)中的有效性,可見性,可更新性(需要鎖的幫助才能正確執(zhí)行隔離級(jí)別)
- 判斷條件:若xmin等于當(dāng)前事務(wù)ID,則包含所有xmax=0(未被刪除)的元組。
若與xmin相等的事務(wù)ID對(duì)應(yīng)的事務(wù)已經(jīng)被提交,則包含所有xmax=0或xmax為當(dāng)前事務(wù)ID的元組。 - 實(shí)現(xiàn)概要
- 對(duì)讀不用加鎖,對(duì)寫加鎖(只阻塞寫),事務(wù)結(jié)束對(duì)比是否沖突
多行數(shù)據(jù)需要過期版本回收
- 頁(yè)面級(jí):頁(yè)面訪問時(shí)回收
- 表級(jí)/系統(tǒng)級(jí): autovacuum; vacuum
日志
- pg_log:數(shù)據(jù)庫(kù)活動(dòng)日志(也就是數(shù)據(jù)庫(kù)的操作日志);
- pg_xlog:事務(wù)日志,記錄事務(wù)的執(zhí)行過程,redo日志
- pg_clog:事務(wù)狀態(tài)日志(pg_clog是pg_xlog的輔助日志),記錄事務(wù)的結(jié)果。
希望本文所述對(duì)大家PostgreSQL數(shù)據(jù)庫(kù)程序設(shè)計(jì)有所幫助。
- PostgreSQL如何查看事務(wù)所占有的鎖實(shí)操指南
- PostgreSQL 存儲(chǔ)過程的進(jìn)階講解(含游標(biāo)、錯(cuò)誤處理、自定義函數(shù)、事務(wù))
- PostgreSQL長(zhǎng)事務(wù)與失效的索引查詢淺析介紹
- PostgreSQL長(zhǎng)事務(wù)概念解析
- PostgreSQL數(shù)據(jù)庫(kù)事務(wù)插入刪除及更新操作示例
- PostgreSQL事務(wù)回卷實(shí)戰(zhàn)案例詳析
- 基于Postgresql 事務(wù)的提交與回滾解析
- PostgreSQL數(shù)據(jù)庫(kù)事務(wù)出現(xiàn)未知狀態(tài)的處理方法
- 深入理解PostgreSQL 事務(wù)處理
相關(guān)文章
Postgresql 查看SQL語句執(zhí)行效率的操作
這篇文章主要介紹了Postgresql 查看SQL語句執(zhí)行效率的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
基于PostgreSQL pg_hba.conf 配置參數(shù)的使用說明
這篇文章主要介紹了基于PostgreSQL pg_hba.conf 配置參數(shù)的使用說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
Postgresql常用函數(shù)及使用方法大全(看一篇就夠了)
使用函數(shù)可以極大的提高用戶對(duì)數(shù)據(jù)庫(kù)的管理效率,函數(shù)表示輸入?yún)?shù)表示一個(gè)具有特定關(guān)系的值,下面這篇文章主要給大家介紹了關(guān)于Postgresql常用函數(shù)及使用方法的相關(guān)資料,需要的朋友可以參考下2022-11-11
詳解PostgreSql數(shù)據(jù)庫(kù)對(duì)象信息及應(yīng)用
這篇文章主要介紹了PostgreSql數(shù)據(jù)庫(kù)對(duì)象信息及應(yīng)用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
基于postgresql行級(jí)鎖for update測(cè)試
這篇文章主要介紹了基于postgresql行級(jí)鎖for update測(cè)試,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12
PostgreSQL數(shù)據(jù)庫(kù)中如何保證LIKE語句的效率(推薦)
這篇文章主要介紹了PostgreSQL數(shù)據(jù)庫(kù)中如何保證LIKE語句的效率,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
Postgresql開啟遠(yuǎn)程訪問的步驟全紀(jì)錄
postgre一般默認(rèn)為本地連接,不支持遠(yuǎn)程訪問,所以如果要開啟遠(yuǎn)程訪問,需要更改安裝文件的配置。下面這篇文章主要給大家介紹了關(guān)于Postgresql開啟遠(yuǎn)程訪問的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2018-03-03

