1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-28 11:44:57 +03:00

Immediately WAL-log subtransaction and top-level XID association.

The logical decoding infrastructure needs to know which top-level
transaction the subxact belongs to, in order to decode all the
changes. Until now that might be delayed until commit, due to the
caching (GPROC_MAX_CACHED_SUBXIDS), preventing features requiring
incremental decoding.

So we also write the assignment info into WAL immediately, as part
of the next WAL record (to minimize overhead) only when wal_level=logical.
We can not remove the existing XLOG_XACT_ASSIGNMENT WAL as that is
required for avoiding overflow in the hot standby snapshot.

Bump XLOG_PAGE_MAGIC, since this introduces XLR_BLOCK_ID_TOPLEVEL_XID.

Author: Tomas Vondra, Dilip Kumar, Amit Kapila
Reviewed-by: Amit Kapila
Tested-by: Neha Sharma and Mahendra Singh Thalor
Discussion: https://postgr.es/m/688b0b7f-2f6c-d827-c27b-216a8e3ea700@2ndquadrant.com
This commit is contained in:
Amit Kapila
2020-07-20 08:48:26 +05:30
parent d05b172a76
commit 0bead9af48
9 changed files with 108 additions and 24 deletions

View File

@@ -191,6 +191,7 @@ typedef struct TransactionStateData
bool didLogXid; /* has xid been included in WAL record? */
int parallelModeLevel; /* Enter/ExitParallelMode counter */
bool chain; /* start a new block after this one */
bool assigned; /* assigned to top-level XID */
struct TransactionStateData *parent; /* back link to parent */
} TransactionStateData;
@@ -223,6 +224,7 @@ typedef struct SerializedTransactionState
static TransactionStateData TopTransactionStateData = {
.state = TRANS_DEFAULT,
.blockState = TBLOCK_DEFAULT,
.assigned = false,
};
/*
@@ -5120,6 +5122,7 @@ PushTransaction(void)
GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
s->prevXactReadOnly = XactReadOnly;
s->parallelModeLevel = 0;
s->assigned = false;
CurrentTransactionState = s;
@@ -6022,3 +6025,50 @@ xact_redo(XLogReaderState *record)
else
elog(PANIC, "xact_redo: unknown op code %u", info);
}
/*
* IsSubTransactionAssignmentPending
*
* This is used to decide whether we need to WAL log the top-level XID for
* operation in a subtransaction. We require that for logical decoding, see
* LogicalDecodingProcessRecord.
*
* This returns true if wal_level >= logical and we are inside a valid
* subtransaction, for which the assignment was not yet written to any WAL
* record.
*/
bool
IsSubTransactionAssignmentPending(void)
{
/* wal_level has to be logical */
if (!XLogLogicalInfoActive())
return false;
/* we need to be in a transaction state */
if (!IsTransactionState())
return false;
/* it has to be a subtransaction */
if (!IsSubTransaction())
return false;
/* the subtransaction has to have a XID assigned */
if (!TransactionIdIsValid(GetCurrentTransactionIdIfAny()))
return false;
/* and it should not be already 'assigned' */
return !CurrentTransactionState->assigned;
}
/*
* MarkSubTransactionAssigned
*
* Mark the subtransaction assignment as completed.
*/
void
MarkSubTransactionAssigned(void)
{
Assert(IsSubTransactionAssignmentPending());
CurrentTransactionState->assigned = true;
}