91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解PostgreSQL事務管理中的子事務

發布時間:2021-11-08 16:17:02 來源:億速云 閱讀:302 作者:iii 欄目:關系型數據庫

本篇內容主要講解“怎么理解PostgreSQL事務管理中的子事務”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么理解PostgreSQL事務管理中的子事務”吧!

一、Subtransaction Handling

README

Subtransaction Handling
-----------------------
子事務處理
Subtransactions are implemented using a stack of TransactionState structures,
each of which has a pointer to its parent transaction's struct.  When a new
subtransaction is to be opened, PushTransaction is called, which creates a new
TransactionState, with its parent link pointing to the current transaction.
StartSubTransaction is in charge of initializing the new TransactionState to
sane values, and properly initializing other subsystems (AtSubStart routines).
子事務通過TransactionState結構體棧來實現,每一個TransactionState都有指向其父事務結構體的指針.
新的子事務即將開啟時,調用PushTransaction,該函數創建TransactionState結構體,parent指向當前事務.
StartSubTransaction負責完整初始化新的TransactionState結構體,并正確初始化其他子系統(AtSubStart例程實現).
When closing a subtransaction, either CommitSubTransaction has to be called
(if the subtransaction is committing), or AbortSubTransaction and
CleanupSubTransaction (if it's aborting).  In either case, PopTransaction is
called so the system returns to the parent transaction.
在關閉子事務時,成功則調用CommitSubTransaction,取消/失敗則調用AbortSubTransaction和CleanupSubTransaction.
無論哪種情況,都會調用PopTransaction以便返回到父事務.
One important point regarding subtransaction handling is that several may need
to be closed in response to a single user command.  That's because savepoints
have names, and we allow to commit or rollback a savepoint by name, which is
not necessarily the one that was last opened.  Also a COMMIT or ROLLBACK
command must be able to close out the entire stack.  We handle this by having
the utility command subroutine mark all the state stack entries as commit-
pending or abort-pending, and then when the main loop reaches
CommitTransactionCommand, the real work is done.  The main point of doing
things this way is that if we get an error while popping state stack entries,
the remaining stack entries still show what we need to do to finish up.
子事務處理一個很很重要的點是為了響應單個用戶命令需要關閉多個子事務.
這是因為對于命名savepoints,PG允許通過名稱提交或回滾至這些savepoint,而這些savepoint并不需要是最后才打開的那個.
同時,COMMIT/ROLLBACK命令必須可以關閉整個棧.
通過工具命令子例程來標記整個狀態棧為commit-pending或者是abort-pending,
然后在主循環到達CommitTransactionCommand時,執行實際的commit/abort.
以這種方法做這些事情的主要關注點是如果在棧條目出棧時出現錯誤,剩余的棧條目仍然可以展示我們需要做什么才能完結.
In the case of ROLLBACK TO <savepoint>, we abort all the subtransactions up
through the one identified by the savepoint name, and then re-create that
subtransaction level with the same name.  So it's a completely new
subtransaction as far as the internals are concerned.
在ROLLBACK TO <savepoint>這種情況中,我們取消了從savepoint name到當前的所有子事務,
然后使用相同的名稱重建了該子事務.因此這是內部需要關注的完全的子事務.
Other subsystems are allowed to start "internal" subtransactions, which are
handled by BeginInternalSubTransaction.  This is to allow implementing
exception handling, e.g. in PL/pgSQL.  ReleaseCurrentSubTransaction and
RollbackAndReleaseCurrentSubTransaction allows the subsystem to close said
subtransactions.  The main difference between this and the savepoint/release
path is that we execute the complete state transition immediately in each
subroutine, rather than deferring some work until CommitTransactionCommand.
Another difference is that BeginInternalSubTransaction is allowed when no
explicit transaction block has been established, while DefineSavepoint is not.
其他子系統允許通過BeginInternalSubTransaction函數啟動"internal"子事務.
因此可以在諸如PL/pgSQL等編程語言中可以實現異常處理.
ReleaseCurrentSubTransaction和RollbackAndReleaseCurrentSubTransaction允許子系統關閉子事務.
這種方式跟savepoint/release的不同點是在每一個子例程中我們馬上執行了完整的狀態變換,
而不是等到執行CommitTransactionCommand才執行某些工作.
另外一個不同點是在沒有創建顯式事務塊的情況下允許調用BeginInternalSubTransaction,
而savepoint則需要明確的DefineSavepoint.
Transaction and Subtransaction Numbering
----------------------------------------
事務和子事務編號
Transactions and subtransactions are assigned permanent XIDs only when/if
they first do something that requires one --- typically, insert/update/delete
a tuple, though there are a few other places that need an XID assigned.
If a subtransaction requires an XID, we always first assign one to its
parent.  This maintains the invariant that child transactions have XIDs later
than their parents, which is assumed in a number of places.
事務和子事務在需要時才會分配持久的XIDs,典型的場景是insert/update/delete元組.
如果子事務需要XID,首先會給其父事務分配一個,這保證了子事務編號在父事務之后.
The subsidiary actions of obtaining a lock on the XID and entering it into
pg_subtrans and PG_PROC are done at the time it is assigned.
分配事務號還需要做的事情是在XID獲取鎖/寫入到pg_subtrans和PG_PROC中.
A transaction that has no XID still needs to be identified for various
purposes, notably holding locks.  For this purpose we assign a "virtual
transaction ID" or VXID to each top-level transaction.  VXIDs are formed from
two fields, the backendID and a backend-local counter; this arrangement allows
assignment of a new VXID at transaction start without any contention for
shared memory.  To ensure that a VXID isn't re-used too soon after backend
exit, we store the last local counter value into shared memory at backend
exit, and initialize it from the previous value for the same backendID slot
at backend start.  All these counters go back to zero at shared memory
re-initialization, but that's OK because VXIDs never appear anywhere on-disk.
沒有XID的事務仍然需要進行標識,特別是需要持有鎖的時候.
出于這個目的,我們分配了"虛擬事務號"(即VXID)給每一個頂層事務.
VXIDs由兩個域組成,后臺進程ID和后臺進程本地計數器;這樣的編號產生方法不需要共享內存爭用就可以進行新VXID的分配.
為了確保在后臺進程退出后VXID不會過快的被使用,我們把最后的本地計數器值存儲到共享內存中,
對于同一個后臺進程ID,分配先前存儲的計數器值給這個新的后臺進程.
在共享內存重新初始化后這些計數器會歸零,由于不會出現落盤,因此這樣的處理沒有任何問題.
Internally, a backend needs a way to identify subtransactions whether or not
they have XIDs; but this need only lasts as long as the parent top transaction
endures.  Therefore, we have SubTransactionId, which is somewhat like
CommandId in that it's generated from a counter that we reset at the start of
each top transaction.  The top-level transaction itself has SubTransactionId 1,
and subtransactions have IDs 2 and up.  (Zero is reserved for
InvalidSubTransactionId.)  Note that subtransactions do not have their
own VXIDs; they use the parent top transaction's VXID.
在內部實現上,不論子事務是否擁有XIDs,后臺進程需要標識子事務的方法;只要父頂級事務存在這種需求就好一直存在.
因此,產生了SubTransactionId,該字段類似于CommandId,在每次頂層事務都會重置的計數器.
頂層事務本身的SubTransactionId設定為1,其他子事務的ID為2或更大(0保留用于InvalidSubTransactionId).
注意子事務沒有VXIDs;它們使用頂層事務的VXID.

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事務管理中的子事務”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

子洲县| 伊通| 福贡县| 运城市| 鄂温| 开平市| 松滋市| 襄汾县| 香港| 潼南县| 砀山县| 乐山市| 陈巴尔虎旗| 石嘴山市| 南部县| 香港| 宁都县| 黔西县| 华池县| 原平市| 奉新县| 古田县| 庐江县| 巢湖市| 定兴县| 文化| 合江县| 饶平县| 旺苍县| 阳山县| 莱州市| 家居| 共和县| 亳州市| 西畴县| 鄄城县| 土默特右旗| 古交市| 益阳市| 张家口市| 沁阳市|