久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

怎么理解PostgreSQL事務管理

197次閱讀
沒有評論

共計 10775 個字符,預計需要花費 27 分鐘才能閱讀完成。

本篇內容介紹了“怎么理解 PostgreSQL 事務管理”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

一、The Transaction System

README

src/backend/access/transam/README
The Transaction System
======================
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 的事務分為 3 層, 底層實現了低層次的事務和子事務, 在其頂上駐留主循環控制代碼,
而主循環實現了用戶可見性事務和保存點.
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
在處理查詢的前后或者檢測到錯誤時,postgres.c 會調用中間層的代碼:
 StartTransactionCommand
 CommitTransactionCommand
 AbortCurrentTransaction
在此期間, 通過執行 BEGIN/COMMIT/ROLLBACK/SAVEPOINT/ROLLBACK TO/RELEASE 命令改變系統狀態.
調度程序會把這些調用重定向至相應的頂層例程上.
 BeginTransactionBlock
 EndTransactionBlock
 UserAbortTransactionBlock
 DefineSavepoint
 RollbackToSavepoint
 ReleaseSavepoint
依賴于當前的系統狀態, 這些函數調用底層函數激活真正的事務系統:
 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.)
另外, 在事務內, 調用 CommandCounterIncrement 增加命令計數, 這可以讓未來的命令可以看到
在同一個事務中先前命令的影響.
注意該動作由 CommitTransactionCommand 在事務塊內部完成每個查詢后自動完成,
但某些工具函數同樣會內部實現此功能以允許某些操作 (通常在系統目錄中) 可被未來同樣的工具命令看到.
(比如, 在 DefineRelation, 在創建堆后已完成, 因此 pg_class 中的行已可見, 并能執行鎖定)
For example, consider the following sequence of user commands:
舉個例子, 考慮下面一組用戶命令:
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:
在主處理循環, 會形成下面函數調用序列:
 / 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.
該例子想表達的意思是 StartTransactionCommand 和 CommitTransactionCommand 需要具備狀態智能
--  在 BeginTransactionBlock/EndTransactionBlock 之間需調用 CommandCounterIncrement,
在這些調用之外, 它們需要執行常規的 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 TO  savepoint  commands.
而且, 假定 SELECT * FROM foo 出錯, 導致需要 abort, 那么會調用 AbortCurrentTransaction(bottom),
事務狀態為 aborted 狀態. 事務處于這個狀態, 除了事務終止語句或者 ROLLBACK TO  savepoint 命令外, 所有用戶輸入都會被忽略.
Transaction aborts can occur in two ways:
事務取消的情況有兩種:
1) system dies from some internal cause (syntax error, etc)
  內部原因, 如語法錯誤等.
2) user types ROLLBACK
  用戶類型的 ROLLBACK.
The reason we have to distinguish them is illustrated by the following two
situations:
區分事務取消的原因如下兩例所示:
 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.
第一種情況, 用戶希望取消事務并返回到默認狀態.
第二種情況, 在同一個事務塊中, 可能會有更多的命令進入, 需要忽略這些命令直至 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
內部的事務取消通過 AbortCurrentTransaction(bottom)處理, 而用戶取消通過 UserAbortTransactionBlock(top)處理.
它們都需要依賴 AbortTransaction(bottom)來處理實際的工作, 不同的地方是在 AbortTransaction 后進入的狀態不同:
* AbortCurrentTransaction 進入 TBLOCK_ABORT
* UserAbortTransactionBlock 進入 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.
底層事務取消處理分為兩個階段:
*  一旦感知事務已失敗, 則馬上執行 AbortTransaction, 需要釋放所有的共享資源 (比如鎖等) 以便不影響其他后臺進程.
*  在用戶發出 COMMIT/ROLLBACK 時執行 CleanupTransaction; 清理現場并完整的跳出事務.
  特別地, 在這個點上才需要銷毀 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).
同時, 注意如果事務已提交, 必須要馬上關閉, 而是進入 TBLOCK_END 狀態,
這意味著在查詢完成后執行 CommitTransactionCommand, 事務才會關閉.
這種區別很微妙,但很重要, 因為控制已在事務開啟的情況下從 xact.c 代碼中跳出, 主循環仍在相同的主事務中.
因此, 在某種意義上來說, 事務提交存在兩個階段, 首先 EndTransactionBlock(top), 其次 CommitTransactionCommand(middle).
(CommitTransactionCommand 是實際調用 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 的剩余代碼是用于支持創建和結束事務和子事務的例程.
比如 AtStart_Memory 在主事務開啟時處理初始化內存子系統.

TransactionState 結構體

/*
 * 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 事務管理”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注丸趣 TV 網站,丸趣 TV 小編將為大家輸出更多高質量的實用文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-26發表,共計10775字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 高台县| 岑巩县| 固安县| 饶河县| 仪陇县| 神木县| 南陵县| 浦城县| 大邑县| 白玉县| 安陆市| 邻水| 宣城市| 漳浦县| 鄂托克前旗| 寻甸| 西安市| 兴义市| 陈巴尔虎旗| 延津县| 杭锦后旗| 玛纳斯县| 湖北省| 琼结县| 麻城市| 马尔康县| 普陀区| 韶关市| 陕西省| 梁河县| 盱眙县| 巫山县| 周至县| 高陵县| 福泉市| 惠州市| 宿迁市| 闸北区| 乌拉特后旗| 山阴县| 隆德县|