mirror of
https://github.com/postgres/postgres.git
synced 2025-07-26 01:22:12 +03:00
Allow decoding at prepare time in ReorderBuffer.
This patch allows PREPARE-time decoding of two-phase transactions (if the
output plugin supports this capability), in which case the transactions
are replayed at PREPARE and then committed later when COMMIT PREPARED
arrives.
Now that we decode the changes before the commit, the concurrent aborts
may cause failures when the output plugin consults catalogs (both system
and user-defined).
We detect such failures with a special sqlerrcode
ERRCODE_TRANSACTION_ROLLBACK introduced by commit 7259736a6e
and stop
decoding the remaining changes. Then we rollback the changes when rollback
prepared is encountered.
Author: Ajin Cherian and Amit Kapila based on previous work by Nikhil Sontakke and Stas Kelvich
Reviewed-by: Amit Kapila, Peter Smith, Sawada Masahiko, Arseny Sher, and Dilip Kumar
Tested-by: Takamichi Osumi
Discussion:
https://postgr.es/m/02DA5F5E-CECE-4D9C-8B4B-418077E2C010@postgrespro.ru
https://postgr.es/m/CAMGcDxeqEpWj3fTXwqhSwBdXd2RS9jzwWscO-XbeCfso6ts3+Q@mail.gmail.com
This commit is contained in:
@ -174,6 +174,8 @@ typedef struct ReorderBufferChange
|
||||
#define RBTXN_IS_STREAMED 0x0010
|
||||
#define RBTXN_HAS_TOAST_INSERT 0x0020
|
||||
#define RBTXN_HAS_SPEC_INSERT 0x0040
|
||||
#define RBTXN_PREPARE 0x0080
|
||||
#define RBTXN_SKIPPED_PREPARE 0x0100
|
||||
|
||||
/* Does the transaction have catalog changes? */
|
||||
#define rbtxn_has_catalog_changes(txn) \
|
||||
@ -233,6 +235,18 @@ typedef struct ReorderBufferChange
|
||||
((txn)->txn_flags & RBTXN_IS_STREAMED) != 0 \
|
||||
)
|
||||
|
||||
/* Has this transaction been prepared? */
|
||||
#define rbtxn_prepared(txn) \
|
||||
( \
|
||||
((txn)->txn_flags & RBTXN_PREPARE) != 0 \
|
||||
)
|
||||
|
||||
/* prepare for this transaction skipped? */
|
||||
#define rbtxn_skip_prepared(txn) \
|
||||
( \
|
||||
((txn)->txn_flags & RBTXN_SKIPPED_PREPARE) != 0 \
|
||||
)
|
||||
|
||||
typedef struct ReorderBufferTXN
|
||||
{
|
||||
/* See above */
|
||||
@ -258,10 +272,11 @@ typedef struct ReorderBufferTXN
|
||||
XLogRecPtr first_lsn;
|
||||
|
||||
/* ----
|
||||
* LSN of the record that lead to this xact to be committed or
|
||||
* LSN of the record that lead to this xact to be prepared or committed or
|
||||
* aborted. This can be a
|
||||
* * plain commit record
|
||||
* * plain commit record, of a parent transaction
|
||||
* * prepared tansaction
|
||||
* * prepared transaction commit
|
||||
* * plain abort record
|
||||
* * prepared transaction abort
|
||||
@ -293,7 +308,8 @@ typedef struct ReorderBufferTXN
|
||||
XLogRecPtr origin_lsn;
|
||||
|
||||
/*
|
||||
* Commit time, only known when we read the actual commit record.
|
||||
* Commit or Prepare time, only known when we read the actual commit or
|
||||
* prepare record.
|
||||
*/
|
||||
TimestampTz commit_time;
|
||||
|
||||
@ -625,12 +641,18 @@ void ReorderBufferQueueMessage(ReorderBuffer *, TransactionId, Snapshot snapsho
|
||||
void ReorderBufferCommit(ReorderBuffer *, TransactionId,
|
||||
XLogRecPtr commit_lsn, XLogRecPtr end_lsn,
|
||||
TimestampTz commit_time, RepOriginId origin_id, XLogRecPtr origin_lsn);
|
||||
void ReorderBufferFinishPrepared(ReorderBuffer *rb, TransactionId xid,
|
||||
XLogRecPtr commit_lsn, XLogRecPtr end_lsn,
|
||||
TimestampTz commit_time,
|
||||
RepOriginId origin_id, XLogRecPtr origin_lsn,
|
||||
char *gid, bool is_commit);
|
||||
void ReorderBufferAssignChild(ReorderBuffer *, TransactionId, TransactionId, XLogRecPtr commit_lsn);
|
||||
void ReorderBufferCommitChild(ReorderBuffer *, TransactionId, TransactionId,
|
||||
XLogRecPtr commit_lsn, XLogRecPtr end_lsn);
|
||||
void ReorderBufferAbort(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
|
||||
void ReorderBufferAbortOld(ReorderBuffer *, TransactionId xid);
|
||||
void ReorderBufferForget(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
|
||||
void ReorderBufferInvalidate(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
|
||||
|
||||
void ReorderBufferSetBaseSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
|
||||
void ReorderBufferAddSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
|
||||
@ -644,10 +666,17 @@ void ReorderBufferAddInvalidations(ReorderBuffer *, TransactionId, XLogRecPtr l
|
||||
void ReorderBufferImmediateInvalidation(ReorderBuffer *, uint32 ninvalidations,
|
||||
SharedInvalidationMessage *invalidations);
|
||||
void ReorderBufferProcessXid(ReorderBuffer *, TransactionId xid, XLogRecPtr lsn);
|
||||
|
||||
void ReorderBufferXidSetCatalogChanges(ReorderBuffer *, TransactionId xid, XLogRecPtr lsn);
|
||||
bool ReorderBufferXidHasCatalogChanges(ReorderBuffer *, TransactionId xid);
|
||||
bool ReorderBufferXidHasBaseSnapshot(ReorderBuffer *, TransactionId xid);
|
||||
|
||||
bool ReorderBufferRememberPrepareInfo(ReorderBuffer *rb, TransactionId xid,
|
||||
XLogRecPtr prepare_lsn, XLogRecPtr end_lsn,
|
||||
TimestampTz prepare_time,
|
||||
RepOriginId origin_id, XLogRecPtr origin_lsn);
|
||||
void ReorderBufferSkipPrepare(ReorderBuffer *rb, TransactionId xid);
|
||||
void ReorderBufferPrepare(ReorderBuffer *rb, TransactionId xid, char *gid);
|
||||
ReorderBufferTXN *ReorderBufferGetOldestTXN(ReorderBuffer *);
|
||||
TransactionId ReorderBufferGetOldestXmin(ReorderBuffer *rb);
|
||||
|
||||
|
Reference in New Issue
Block a user