新聞中心
本篇內(nèi)容介紹了“怎么理解PostgreSQL事務(wù)管理”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
黃陵ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書(shū)合作)期待與您的合作!
一、The Transaction System
README
src/backend/access/transam/README The Transaction System ====================== 事務(wù)系統(tǒng) PostgreSQL's transaction system is a three-layer system. The bottom layer implements low-level transactions and subtransactions, on top of which rests the mainloop's control code, which in turn implements user-visible transactions and savepoints. PostgreSQL的事務(wù)分為3層,底層實(shí)現(xiàn)了低層次的事務(wù)和子事務(wù),在其頂上駐留主循環(huán)控制代碼, 而主循環(huán)實(shí)現(xiàn)了用戶可見(jiàn)性事務(wù)和保存點(diǎn). The middle layer of code is called by postgres.c before and after the processing of each query, or after detecting an error: StartTransactionCommand CommitTransactionCommand AbortCurrentTransaction Meanwhile, the user can alter the system's state by issuing the SQL commands BEGIN, COMMIT, ROLLBACK, SAVEPOINT, ROLLBACK TO or RELEASE. The traffic cop redirects these calls to the toplevel routines BeginTransactionBlock EndTransactionBlock UserAbortTransactionBlock DefineSavepoint RollbackToSavepoint ReleaseSavepoint respectively. Depending on the current state of the system, these functions call low level functions to activate the real transaction system: StartTransaction CommitTransaction AbortTransaction CleanupTransaction StartSubTransaction CommitSubTransaction AbortSubTransaction CleanupSubTransaction 在處理查詢的前后或者檢測(cè)到錯(cuò)誤時(shí),postgres.c會(huì)調(diào)用中間層的代碼: StartTransactionCommand CommitTransactionCommand AbortCurrentTransaction 在此期間,通過(guò)執(zhí)行BEGIN/COMMIT/ROLLBACK/SAVEPOINT/ROLLBACK TO/RELEASE命令改變系統(tǒng)狀態(tài). 調(diào)度程序會(huì)把這些調(diào)用重定向至相應(yīng)的頂層例程上. BeginTransactionBlock EndTransactionBlock UserAbortTransactionBlock DefineSavepoint RollbackToSavepoint ReleaseSavepoint 依賴于當(dāng)前的系統(tǒng)狀態(tài),這些函數(shù)調(diào)用底層函數(shù)激活真正的事務(wù)系統(tǒng): StartTransaction CommitTransaction AbortTransaction CleanupTransaction StartSubTransaction CommitSubTransaction AbortSubTransaction CleanupSubTransaction Additionally, within a transaction, CommandCounterIncrement is called to increment the command counter, which allows future commands to "see" the effects of previous commands within the same transaction. Note that this is done automatically by CommitTransactionCommand after each query inside a transaction block, but some utility functions also do it internally to allow some operations (usually in the system catalogs) to be seen by future operations in the same utility command. (For example, in DefineRelation it is done after creating the heap so the pg_class row is visible, to be able to lock it.) 另外,在事務(wù)內(nèi),調(diào)用CommandCounterIncrement增加命令計(jì)數(shù),這可以讓未來(lái)的命令可以看到 在同一個(gè)事務(wù)中先前命令的影響. 注意該動(dòng)作由CommitTransactionCommand在事務(wù)塊內(nèi)部完成每個(gè)查詢后自動(dòng)完成, 但某些工具函數(shù)同樣會(huì)內(nèi)部實(shí)現(xiàn)此功能以允許某些操作(通常在系統(tǒng)目錄中)可被未來(lái)同樣的工具命令看到. (比如,在DefineRelation,在創(chuàng)建堆后已完成,因此pg_class中的行已可見(jiàn),并能執(zhí)行鎖定) For example, consider the following sequence of user commands: 舉個(gè)例子,考慮下面一組用戶命令: 1) BEGIN 2) SELECT * FROM foo 3) INSERT INTO foo VALUES (...) 4) COMMIT In the main processing loop, this results in the following function call sequence: 在主處理循環(huán),會(huì)形成下面函數(shù)調(diào)用序列: / StartTransactionCommand; -- middle / StartTransaction; -- bottom 1) < ProcessUtility; << BEGIN \ BeginTransactionBlock; -- top \ CommitTransactionCommand; -- middle / StartTransactionCommand; -- middle 2) / PortalRunSelect; << SELECT ... \ CommitTransactionCommand; -- middle \ CommandCounterIncrement; / StartTransactionCommand; -- middle 3) / ProcessQuery; << INSERT ... \ CommitTransactionCommand; -- middle \ CommandCounterIncrement; / StartTransactionCommand; -- middle / ProcessUtility; << COMMIT 4) < EndTransactionBlock; -- top \ CommitTransactionCommand; -- middle \ CommitTransaction; -- bottom The point of this example is to demonstrate the need for StartTransactionCommand and CommitTransactionCommand to be state smart -- they should call CommandCounterIncrement between the calls to BeginTransactionBlock and EndTransactionBlock and outside these calls they need to do normal start, commit or abort processing. 該例子想表達(dá)的意思是StartTransactionCommand和CommitTransactionCommand需要具備狀態(tài)智能 -- 在BeginTransactionBlock/EndTransactionBlock之間需調(diào)用CommandCounterIncrement, 在這些調(diào)用之外,它們需要執(zhí)行常規(guī)的start,commit或abort處理. Furthermore, suppose the "SELECT * FROM foo" caused an abort condition. In this case AbortCurrentTransaction is called, and the transaction is put in aborted state. In this state, any user input is ignored except for transaction-termination statements, or ROLLBACK TOcommands. 而且,假定"SELECT * FROM foo"出錯(cuò),導(dǎo)致需要abort,那么會(huì)調(diào)用AbortCurrentTransaction(bottom), 事務(wù)狀態(tài)為aborted狀態(tài).事務(wù)處于這個(gè)狀態(tài),除了事務(wù)終止語(yǔ)句或者ROLLBACK TO 命令外,所有用戶輸入都會(huì)被忽略. Transaction aborts can occur in two ways: 事務(wù)取消的情況有兩種: 1) system dies from some internal cause (syntax error, etc) 內(nèi)部原因,如語(yǔ)法錯(cuò)誤等. 2) user types ROLLBACK 用戶類型的ROLLBACK. The reason we have to distinguish them is illustrated by the following two situations: 區(qū)分事務(wù)取消的原因如下兩例所示: case 1 case 2 ------ ------ 1) user types BEGIN 1) user types BEGIN 2) user does something 2) user does something 3) user does not like what 3) system aborts for some reason she sees and types ABORT (syntax error, etc) In case 1, we want to abort the transaction and return to the default state. In case 2, there may be more commands coming our way which are part of the same transaction block; we have to ignore these commands until we see a COMMIT or ROLLBACK. 第一種情況,用戶希望取消事務(wù)并返回到默認(rèn)狀態(tài). 第二種情況,在同一個(gè)事務(wù)塊中,可能會(huì)有更多的命令進(jìn)入,需要忽略這些命令直至COMMIT/ROLLBACK. Internal aborts are handled by AbortCurrentTransaction, while user aborts are handled by UserAbortTransactionBlock. Both of them rely on AbortTransaction to do all the real work. The only difference is what state we enter after AbortTransaction does its work: * AbortCurrentTransaction leaves us in TBLOCK_ABORT, * UserAbortTransactionBlock leaves us in TBLOCK_ABORT_END 內(nèi)部的事務(wù)取消通過(guò)AbortCurrentTransaction(bottom)處理,而用戶取消通過(guò)UserAbortTransactionBlock(top)處理. 它們都需要依賴AbortTransaction(bottom)來(lái)處理實(shí)際的工作,不同的地方是在AbortTransaction后進(jìn)入的狀態(tài)不同: * AbortCurrentTransaction進(jìn)入TBLOCK_ABORT * UserAbortTransactionBlock進(jìn)入TBLOCK_ABORT_END Low-level transaction abort handling is divided in two phases: * AbortTransaction executes as soon as we realize the transaction has failed. It should release all shared resources (locks etc) so that we do not delay other backends unnecessarily. * CleanupTransaction executes when we finally see a user COMMIT or ROLLBACK command; it cleans things up and gets us out of the transaction completely. In particular, we mustn't destroy TopTransactionContext until this point. 底層事務(wù)取消處理分為兩個(gè)階段: * 一旦感知事務(wù)已失敗,則馬上執(zhí)行AbortTransaction,需要釋放所有的共享資源(比如鎖等)以便不影響其他后臺(tái)進(jìn)程. * 在用戶發(fā)出COMMIT/ROLLBACK時(shí)執(zhí)行CleanupTransaction;清理現(xiàn)場(chǎng)并完整的跳出事務(wù). 特別地,在這個(gè)點(diǎn)上才需要銷(xiāo)毀TopTransactionContext Also, note that when a transaction is committed, we don't close it right away. Rather it's put in TBLOCK_END state, which means that when CommitTransactionCommand is called after the query has finished processing, the transaction has to be closed. The distinction is subtle but important, because it means that control will leave the xact.c code with the transaction open, and the main loop will be able to keep processing inside the same transaction. So, in a sense, transaction commit is also handled in two phases, the first at EndTransactionBlock and the second at CommitTransactionCommand (which is where CommitTransaction is actually called). 同時(shí),注意如果事務(wù)已提交,必須要馬上關(guān)閉,而是進(jìn)入TBLOCK_END狀態(tài), 這意味著在查詢完成后執(zhí)行CommitTransactionCommand,事務(wù)才會(huì)關(guān)閉. 這種區(qū)別很微妙,但很重要,因?yàn)榭刂埔言谑聞?wù)開(kāi)啟的情況下從xact.c代碼中跳出,主循環(huán)仍在相同的主事務(wù)中. 因此,在某種意義上來(lái)說(shuō),事務(wù)提交存在兩個(gè)階段,首先EndTransactionBlock(top),其次CommitTransactionCommand(middle). (CommitTransactionCommand是實(shí)際調(diào)用CommitTransaction的地方) The rest of the code in xact.c are routines to support the creation and finishing of transactions and subtransactions. For example, AtStart_Memory takes care of initializing the memory subsystem at main transaction start. xact.c的剩余代碼是用于支持創(chuàng)建和結(jié)束事務(wù)和子事務(wù)的例程. 比如AtStart_Memory在主事務(wù)開(kāi)啟時(shí)處理初始化內(nèi)存子系統(tǒng).
TransactionState結(jié)構(gòu)體
/* * transaction states - transaction state from server perspective */ 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; /* * transaction block states - transaction state of client queries * * Note: the subtransaction states are used only for non-topmost * transactions; the others appear only in the topmost transaction. */ typedef enum TBlockState { /* not-in-transaction-block states */ TBLOCK_DEFAULT, /* idle */ TBLOCK_STARTED, /* running single-query transaction */ /* transaction block states */ TBLOCK_BEGIN, /* starting transaction block */ TBLOCK_INPROGRESS, /* live transaction */ TBLOCK_IMPLICIT_INPROGRESS, /* live transaction after implicit BEGIN */ TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */ TBLOCK_END, /* COMMIT received */ TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */ TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */ TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */ TBLOCK_PREPARE, /* live xact, PREPARE received */ /* 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; /* * transaction state structure */ typedef struct TransactionStateData { FullTransactionId fullTransactionId; /* my FullTransactionId */ SubTransactionId subTransactionId; /* my subxact ID */ char *name; /* savepoint name, if any */ int savepointLevel; /* savepoint level */ TransState state; /* low-level state */ TBlockState blockState; /* high-level state */ int nestingLevel; /* transaction nesting depth */ int gucNestLevel; /* GUC context nesting depth */ MemoryContext curTransactionContext; /* my xact-lifetime context */ ResourceOwner curTransactionOwner; /* my query resources */ TransactionId *childXids; /* subcommitted child XIDs, in XID order */ int nChildXids; /* # of subcommitted child XIDs */ int maxChildXids; /* allocated size of childXids[] */ Oid prevUser; /* previous CurrentUserId setting */ int prevSecContext; /* previous SecurityRestrictionContext */ bool prevXactReadOnly; /* entry-time xact r/o state */ bool startedInRecovery; /* did we start in recovery? */ bool didLogXid; /* has xid been included in WAL record? */ int parallelModeLevel; /* Enter/ExitParallelMode counter */ bool chain; /* start a new block after this one */ struct TransactionStateData *parent; /* back link to parent */ } TransactionStateData; typedef TransactionStateData *TransactionState;
“怎么理解PostgreSQL事務(wù)管理”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
分享名稱:怎么理解PostgreSQL事務(wù)管理
URL鏈接:http://ef60e0e.cn/article/pdohip.html