mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-05 19:09:58 +08:00
Replace XLOG_INCLUDE_XID flag with a more localized flag.
Commit 0bead9af48
introduced XLOG_INCLUDE_XID flag to indicate that the
WAL record contains subXID-to-topXID association. It uses that flag later
to mark in CurrentTransactionState that top-xid is logged so that we
should not try to log it again with the next WAL record in the current
subtransaction. However, we can use a localized variable to pass that
information.
In passing, change the related function and variable names to make them
consistent with what the code is actually doing.
Author: Dilip Kumar
Reviewed-by: Alvaro Herrera, Amit Kapila
Discussion: https://postgr.es/m/E1mSoYz-0007Fh-D9@gemulon.postgresql.org
This commit is contained in:
parent
43a134f28b
commit
71db6459e6
@ -205,7 +205,7 @@ typedef struct TransactionStateData
|
|||||||
bool didLogXid; /* has xid been included in WAL record? */
|
bool didLogXid; /* has xid been included in WAL record? */
|
||||||
int parallelModeLevel; /* Enter/ExitParallelMode counter */
|
int parallelModeLevel; /* Enter/ExitParallelMode counter */
|
||||||
bool chain; /* start a new block after this one */
|
bool chain; /* start a new block after this one */
|
||||||
bool assigned; /* assigned to top-level XID */
|
bool topXidLogged; /* for a subxact: is top-level XID logged? */
|
||||||
struct TransactionStateData *parent; /* back link to parent */
|
struct TransactionStateData *parent; /* back link to parent */
|
||||||
} TransactionStateData;
|
} TransactionStateData;
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ typedef struct SerializedTransactionState
|
|||||||
static TransactionStateData TopTransactionStateData = {
|
static TransactionStateData TopTransactionStateData = {
|
||||||
.state = TRANS_DEFAULT,
|
.state = TRANS_DEFAULT,
|
||||||
.blockState = TBLOCK_DEFAULT,
|
.blockState = TBLOCK_DEFAULT,
|
||||||
.assigned = false,
|
.topXidLogged = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -529,6 +529,56 @@ MarkCurrentTransactionIdLoggedIfAny(void)
|
|||||||
CurrentTransactionState->didLogXid = true;
|
CurrentTransactionState->didLogXid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IsSubxactTopXidLogPending
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
IsSubxactTopXidLogPending(void)
|
||||||
|
{
|
||||||
|
/* check whether it is already logged */
|
||||||
|
if (CurrentTransactionState->topXidLogged)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MarkSubxactTopXidLogged
|
||||||
|
*
|
||||||
|
* Remember that the top transaction id for the current subtransaction is WAL
|
||||||
|
* logged now.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
MarkSubxactTopXidLogged(void)
|
||||||
|
{
|
||||||
|
Assert(IsSubxactTopXidLogPending());
|
||||||
|
|
||||||
|
CurrentTransactionState->topXidLogged = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetStableLatestTransactionId
|
* GetStableLatestTransactionId
|
||||||
@ -5174,7 +5224,7 @@ PushTransaction(void)
|
|||||||
GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
|
GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
|
||||||
s->prevXactReadOnly = XactReadOnly;
|
s->prevXactReadOnly = XactReadOnly;
|
||||||
s->parallelModeLevel = 0;
|
s->parallelModeLevel = 0;
|
||||||
s->assigned = false;
|
s->topXidLogged = false;
|
||||||
|
|
||||||
CurrentTransactionState = s;
|
CurrentTransactionState = s;
|
||||||
|
|
||||||
@ -6106,50 +6156,3 @@ xact_redo(XLogReaderState *record)
|
|||||||
else
|
else
|
||||||
elog(PANIC, "xact_redo: unknown op code %u", info);
|
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;
|
|
||||||
}
|
|
||||||
|
@ -999,6 +999,9 @@ static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt);
|
|||||||
* 'flags' gives more in-depth control on the record being inserted. See
|
* 'flags' gives more in-depth control on the record being inserted. See
|
||||||
* XLogSetRecordFlags() for details.
|
* XLogSetRecordFlags() for details.
|
||||||
*
|
*
|
||||||
|
* 'topxid_included' tells whether the top-transaction id is logged along with
|
||||||
|
* current subtransaction. See XLogRecordAssemble().
|
||||||
|
*
|
||||||
* The first XLogRecData in the chain must be for the record header, and its
|
* The first XLogRecData in the chain must be for the record header, and its
|
||||||
* data must be MAXALIGNed. XLogInsertRecord fills in the xl_prev and
|
* data must be MAXALIGNed. XLogInsertRecord fills in the xl_prev and
|
||||||
* xl_crc fields in the header, the rest of the header must already be filled
|
* xl_crc fields in the header, the rest of the header must already be filled
|
||||||
@ -1014,7 +1017,8 @@ XLogRecPtr
|
|||||||
XLogInsertRecord(XLogRecData *rdata,
|
XLogInsertRecord(XLogRecData *rdata,
|
||||||
XLogRecPtr fpw_lsn,
|
XLogRecPtr fpw_lsn,
|
||||||
uint8 flags,
|
uint8 flags,
|
||||||
int num_fpi)
|
int num_fpi,
|
||||||
|
bool topxid_included)
|
||||||
{
|
{
|
||||||
XLogCtlInsert *Insert = &XLogCtl->Insert;
|
XLogCtlInsert *Insert = &XLogCtl->Insert;
|
||||||
pg_crc32c rdata_crc;
|
pg_crc32c rdata_crc;
|
||||||
@ -1169,6 +1173,13 @@ XLogInsertRecord(XLogRecData *rdata,
|
|||||||
|
|
||||||
END_CRIT_SECTION();
|
END_CRIT_SECTION();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark top transaction id is logged (if needed) so that we should not try
|
||||||
|
* to log it again with the next WAL record in the current subtransaction.
|
||||||
|
*/
|
||||||
|
if (topxid_included)
|
||||||
|
MarkSubxactTopXidLogged();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update shared LogwrtRqst.Write, if we crossed page boundary.
|
* Update shared LogwrtRqst.Write, if we crossed page boundary.
|
||||||
*/
|
*/
|
||||||
|
@ -123,7 +123,8 @@ static MemoryContext xloginsert_cxt;
|
|||||||
|
|
||||||
static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info,
|
static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info,
|
||||||
XLogRecPtr RedoRecPtr, bool doPageWrites,
|
XLogRecPtr RedoRecPtr, bool doPageWrites,
|
||||||
XLogRecPtr *fpw_lsn, int *num_fpi);
|
XLogRecPtr *fpw_lsn, int *num_fpi,
|
||||||
|
bool *topxid_included);
|
||||||
static bool XLogCompressBackupBlock(char *page, uint16 hole_offset,
|
static bool XLogCompressBackupBlock(char *page, uint16 hole_offset,
|
||||||
uint16 hole_length, char *dest, uint16 *dlen);
|
uint16 hole_length, char *dest, uint16 *dlen);
|
||||||
|
|
||||||
@ -209,10 +210,6 @@ XLogResetInsertion(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* reset the subxact assignment flag (if needed) */
|
|
||||||
if (curinsert_flags & XLOG_INCLUDE_XID)
|
|
||||||
MarkSubTransactionAssigned();
|
|
||||||
|
|
||||||
for (i = 0; i < max_registered_block_id; i++)
|
for (i = 0; i < max_registered_block_id; i++)
|
||||||
registered_buffers[i].in_use = false;
|
registered_buffers[i].in_use = false;
|
||||||
|
|
||||||
@ -409,8 +406,6 @@ XLogRegisterBufData(uint8 block_id, char *data, int len)
|
|||||||
* - XLOG_MARK_UNIMPORTANT, to signal that the record is not important for
|
* - XLOG_MARK_UNIMPORTANT, to signal that the record is not important for
|
||||||
* durability, which allows to avoid triggering WAL archiving and other
|
* durability, which allows to avoid triggering WAL archiving and other
|
||||||
* background activity.
|
* background activity.
|
||||||
* - XLOG_INCLUDE_XID, a message-passing hack between XLogRecordAssemble
|
|
||||||
* and XLogResetInsertion.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
XLogSetRecordFlags(uint8 flags)
|
XLogSetRecordFlags(uint8 flags)
|
||||||
@ -465,6 +460,7 @@ XLogInsert(RmgrId rmid, uint8 info)
|
|||||||
{
|
{
|
||||||
XLogRecPtr RedoRecPtr;
|
XLogRecPtr RedoRecPtr;
|
||||||
bool doPageWrites;
|
bool doPageWrites;
|
||||||
|
bool topxid_included = false;
|
||||||
XLogRecPtr fpw_lsn;
|
XLogRecPtr fpw_lsn;
|
||||||
XLogRecData *rdt;
|
XLogRecData *rdt;
|
||||||
int num_fpi = 0;
|
int num_fpi = 0;
|
||||||
@ -477,9 +473,10 @@ XLogInsert(RmgrId rmid, uint8 info)
|
|||||||
GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);
|
GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);
|
||||||
|
|
||||||
rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
|
rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
|
||||||
&fpw_lsn, &num_fpi);
|
&fpw_lsn, &num_fpi, &topxid_included);
|
||||||
|
|
||||||
EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi);
|
EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
|
||||||
|
topxid_included);
|
||||||
} while (EndPos == InvalidXLogRecPtr);
|
} while (EndPos == InvalidXLogRecPtr);
|
||||||
|
|
||||||
XLogResetInsertion();
|
XLogResetInsertion();
|
||||||
@ -498,11 +495,14 @@ XLogInsert(RmgrId rmid, uint8 info)
|
|||||||
* of all of them, *fpw_lsn is set to the lowest LSN among such pages. This
|
* of all of them, *fpw_lsn is set to the lowest LSN among such pages. This
|
||||||
* signals that the assembled record is only good for insertion on the
|
* signals that the assembled record is only good for insertion on the
|
||||||
* assumption that the RedoRecPtr and doPageWrites values were up-to-date.
|
* assumption that the RedoRecPtr and doPageWrites values were up-to-date.
|
||||||
|
*
|
||||||
|
* *topxid_included is set if the topmost transaction ID is logged with the
|
||||||
|
* current subtransaction.
|
||||||
*/
|
*/
|
||||||
static XLogRecData *
|
static XLogRecData *
|
||||||
XLogRecordAssemble(RmgrId rmid, uint8 info,
|
XLogRecordAssemble(RmgrId rmid, uint8 info,
|
||||||
XLogRecPtr RedoRecPtr, bool doPageWrites,
|
XLogRecPtr RedoRecPtr, bool doPageWrites,
|
||||||
XLogRecPtr *fpw_lsn, int *num_fpi)
|
XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
|
||||||
{
|
{
|
||||||
XLogRecData *rdt;
|
XLogRecData *rdt;
|
||||||
uint32 total_len = 0;
|
uint32 total_len = 0;
|
||||||
@ -788,12 +788,12 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* followed by toplevel XID, if not already included in previous record */
|
/* followed by toplevel XID, if not already included in previous record */
|
||||||
if (IsSubTransactionAssignmentPending())
|
if (IsSubxactTopXidLogPending())
|
||||||
{
|
{
|
||||||
TransactionId xid = GetTopTransactionIdIfAny();
|
TransactionId xid = GetTopTransactionIdIfAny();
|
||||||
|
|
||||||
/* update the flag (later used by XLogResetInsertion) */
|
/* Set the flag that the top xid is included in the WAL */
|
||||||
XLogSetRecordFlags(XLOG_INCLUDE_XID);
|
*topxid_included = true;
|
||||||
|
|
||||||
*(scratch++) = (char) XLR_BLOCK_ID_TOPLEVEL_XID;
|
*(scratch++) = (char) XLR_BLOCK_ID_TOPLEVEL_XID;
|
||||||
memcpy(scratch, &xid, sizeof(TransactionId));
|
memcpy(scratch, &xid, sizeof(TransactionId));
|
||||||
|
@ -433,8 +433,8 @@ extern void UnregisterXactCallback(XactCallback callback, void *arg);
|
|||||||
extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
|
extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
|
||||||
extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
|
extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
|
||||||
|
|
||||||
extern bool IsSubTransactionAssignmentPending(void);
|
extern bool IsSubxactTopXidLogPending(void);
|
||||||
extern void MarkSubTransactionAssigned(void);
|
extern void MarkSubxactTopXidLogged(void);
|
||||||
|
|
||||||
extern int xactGetCommittedChildren(TransactionId **ptr);
|
extern int xactGetCommittedChildren(TransactionId **ptr);
|
||||||
|
|
||||||
|
@ -212,7 +212,6 @@ extern bool XLOG_DEBUG;
|
|||||||
*/
|
*/
|
||||||
#define XLOG_INCLUDE_ORIGIN 0x01 /* include the replication origin */
|
#define XLOG_INCLUDE_ORIGIN 0x01 /* include the replication origin */
|
||||||
#define XLOG_MARK_UNIMPORTANT 0x02 /* record not important for durability */
|
#define XLOG_MARK_UNIMPORTANT 0x02 /* record not important for durability */
|
||||||
#define XLOG_INCLUDE_XID 0x04 /* WAL-internal message-passing hack */
|
|
||||||
|
|
||||||
|
|
||||||
/* Checkpoint statistics */
|
/* Checkpoint statistics */
|
||||||
@ -258,7 +257,8 @@ struct XLogRecData;
|
|||||||
extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
|
extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
|
||||||
XLogRecPtr fpw_lsn,
|
XLogRecPtr fpw_lsn,
|
||||||
uint8 flags,
|
uint8 flags,
|
||||||
int num_fpi);
|
int num_fpi,
|
||||||
|
bool topxid_included);
|
||||||
extern void XLogFlush(XLogRecPtr RecPtr);
|
extern void XLogFlush(XLogRecPtr RecPtr);
|
||||||
extern bool XLogBackgroundFlush(void);
|
extern bool XLogBackgroundFlush(void);
|
||||||
extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
|
extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
|
||||||
|
Loading…
Reference in New Issue
Block a user