Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 86e3364

Browse files
Derive oldestActiveXid at correct time for Hot Standby.
There was a timing window between when oldestActiveXid was derived and when it should have been derived that only shows itself under heavy load. Move code around to ensure correct timing of derivation. No change to StartupSUBTRANS() code, which is where this failed. Bug report by Chris Redekop
1 parent 10b7c68 commit 86e3364

File tree

5 files changed

+71
-6
lines changed

5 files changed

+71
-6
lines changed

src/backend/access/transam/xlog.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7636,6 +7636,16 @@ CreateCheckPoint(int flags)
76367636
MemSet(&checkPoint, 0, sizeof(checkPoint));
76377637
checkPoint.time = (pg_time_t) time(NULL);
76387638

7639+
/*
7640+
* For Hot Standby, derive the oldestActiveXid before we fix the redo pointer.
7641+
* This allows us to begin accumulating changes to assemble our starting
7642+
* snapshot of locks and transactions.
7643+
*/
7644+
if (!shutdown && XLogStandbyInfoActive())
7645+
checkPoint.oldestActiveXid = GetOldestActiveTransactionId();
7646+
else
7647+
checkPoint.oldestActiveXid = InvalidTransactionId;
7648+
76397649
/*
76407650
* We must hold WALInsertLock while examining insert state to determine
76417651
* the checkpoint REDO pointer.
@@ -7822,9 +7832,7 @@ CreateCheckPoint(int flags)
78227832
* Update checkPoint.nextXid since we have a later value
78237833
*/
78247834
if (!shutdown && XLogStandbyInfoActive())
7825-
LogStandbySnapshot(&checkPoint.oldestActiveXid, &checkPoint.nextXid);
7826-
else
7827-
checkPoint.oldestActiveXid = InvalidTransactionId;
7835+
LogStandbySnapshot(&checkPoint.nextXid);
78287836

78297837
START_CRIT_SECTION();
78307838

src/backend/storage/ipc/procarray.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,63 @@ GetRunningTransactionData(void)
16201620
return CurrentRunningXacts;
16211621
}
16221622

1623+
/*
1624+
* GetOldestActiveTransactionId()
1625+
*
1626+
* Similar to GetSnapshotData but returns just oldestActiveXid. We include
1627+
* all PGPROCs with an assigned TransactionId, even VACUUM processes.
1628+
* We look at all databases, though there is no need to include WALSender
1629+
* since this has no effect on hot standby conflicts.
1630+
*
1631+
* This is never executed during recovery so there is no need to look at
1632+
* KnownAssignedXids.
1633+
*
1634+
* We don't worry about updating other counters, we want to keep this as
1635+
* simple as possible and leave GetSnapshotData() as the primary code for
1636+
* that bookkeeping.
1637+
*/
1638+
TransactionId
1639+
GetOldestActiveTransactionId(void)
1640+
{
1641+
ProcArrayStruct *arrayP = procArray;
1642+
TransactionId oldestRunningXid;
1643+
int index;
1644+
1645+
Assert(!RecoveryInProgress());
1646+
1647+
LWLockAcquire(ProcArrayLock, LW_SHARED);
1648+
1649+
oldestRunningXid = ShmemVariableCache->nextXid;
1650+
1651+
/*
1652+
* Spin over procArray collecting all xids and subxids.
1653+
*/
1654+
for (index = 0; index < arrayP->numProcs; index++)
1655+
{
1656+
volatile PGPROC *proc = arrayP->procs[index];
1657+
TransactionId xid;
1658+
1659+
/* Fetch xid just once - see GetNewTransactionId */
1660+
xid = proc->xid;
1661+
1662+
if (!TransactionIdIsNormal(xid))
1663+
continue;
1664+
1665+
if (TransactionIdPrecedes(xid, oldestRunningXid))
1666+
oldestRunningXid = xid;
1667+
1668+
/*
1669+
* Top-level XID of a transaction is always less than any of its
1670+
* subxids, so we don't need to check if any of the subxids are
1671+
* smaller than oldestRunningXid
1672+
*/
1673+
}
1674+
1675+
LWLockRelease(ProcArrayLock);
1676+
1677+
return oldestRunningXid;
1678+
}
1679+
16231680
/*
16241681
* GetTransactionsInCommit -- Get the XIDs of transactions that are committing
16251682
*

src/backend/storage/ipc/standby.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ standby_desc(StringInfo buf, uint8 xl_info, char *rec)
815815
* making WAL entries.
816816
*/
817817
void
818-
LogStandbySnapshot(TransactionId *oldestActiveXid, TransactionId *nextXid)
818+
LogStandbySnapshot(TransactionId *nextXid)
819819
{
820820
RunningTransactions running;
821821
xl_standby_lock *locks;
@@ -845,7 +845,6 @@ LogStandbySnapshot(TransactionId *oldestActiveXid, TransactionId *nextXid)
845845
/* GetRunningTransactionData() acquired XidGenLock, we must release it */
846846
LWLockRelease(XidGenLock);
847847

848-
*oldestActiveXid = running->oldestRunningXid;
849848
*nextXid = running->nextXid;
850849
}
851850

src/include/storage/procarray.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern RunningTransactions GetRunningTransactionData(void);
5050
extern bool TransactionIdIsInProgress(TransactionId xid);
5151
extern bool TransactionIdIsActive(TransactionId xid);
5252
extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum);
53+
extern TransactionId GetOldestActiveTransactionId(void);
5354

5455
extern int GetTransactionsInCommit(TransactionId **xids_p);
5556
extern bool HaveTransactionsInCommit(TransactionId *xids, int nxids);

src/include/storage/standby.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,6 @@ typedef RunningTransactionsData *RunningTransactions;
111111
extern void LogAccessExclusiveLock(Oid dbOid, Oid relOid);
112112
extern void LogAccessExclusiveLockPrepare(void);
113113

114-
extern void LogStandbySnapshot(TransactionId *oldestActiveXid, TransactionId *nextXid);
114+
extern void LogStandbySnapshot(TransactionId *nextXid);
115115

116116
#endif /* STANDBY_H */

0 commit comments

Comments
 (0)