/* actual file length */
TransactionId xid;
/* original transaction XID */
Oid
database;
/* OID of database it was in */
TimestampTz prepared_at;
/* time of preparation */
Oid
owner;
/* user running the transaction */
int32
nsubxacts;
/* number of following subxact XIDs */
int32
ncommitrels;
/* number of delete-on-commit rels */
int32
nabortrels;
/* number of delete-on-abort rels */
int32
ninvalmsgs;
/* number of cache invalidation messages */
bool
initfileinval;
/* does relcache init file need invalidation */
char
gid[GIDSIZE];
/* GID for transaction */
} TwoPhaseFileHeader;
Variable
static THREAD_LOCAL TwoPhaseStateData *TwoPhaseState;
4 分布式事务创建
4.1 Where the transcation id is come from?
Each global transaction is associated with a global transaction
identifier (GID). The client assigns a GID to a postgres transaction with the PREPARE TRANSACTION command.
4.2 Where the transaction is stored in server?
We keep all active global transactions in a shared memory array.When the PREPARE TRANSACTION command is issued, the GID is reserved for the transaction in the array. This is done before a WAL entry is made, because the reservation checks for duplicate GIDs and aborts the transaction if there already is a global transaction in prepared state with the same GID.
4.3 global transaction has a dummy PGPROC
A global transaction (gxact) also has a dummy PGPROC that is entered
into the ProcArray array; this is what keeps the XID considered
running by TransactionIdIsInProgress. It is also convenient as a
PGPROC to hook the gxact's locks to.
5 分布式事务Commit
recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT_PREPARED, rdata);
/* Always flush, since we're about to remove the 2PC state file */
XLogFlush(recptr);
/*
* Mark the transaction aborted in clog. This is not absolutely necessary
* but we may as well do it while we are here.
*/
TransactionIdAbortTree(xid, nchildren, children);
5分布式事务Recovery
In order to survive crashes and shutdowns, all prepared transactions must be stored in permanent storage. This includes locking information, pending notifications etc. All that state information is written to the per-transaction state file in the pg_twophase directory.
5.1RecoverPreparedTransactions
In order to survive crashes and shutdowns, all prepared transactions must be stored in permanent storage. This includes locking information, pending notifications etc. All that state information is written to the per-transaction state file in the pg_twophase directory.
5.2RecoverPreparedTransactions
Scan the pg_twophase directory and reload shared-memory state for each
prepared transaction
5.3lock_twophase_standby_recover
Re-acquire a lock belonging to a transaction that was prepared, when starting up into hot standby mode.