1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Track latest completed xid as a FullTransactionId.

The reason for doing so is that a subsequent commit will need that to
avoid wraparound issues. As the subsequent change is large this was
split out for easier review.

The reason this is not a perfect straight-forward change is that we do
not want track 64bit xids in the procarray or the WAL. Therefore we
need to advance lastestCompletedXid in relation to 32 bit xids. The
code for that is now centralized in MaintainLatestCompletedXid*.

Author: Andres Freund
Reviewed-By: Thomas Munro, Robert Haas, David Rowley
Discussion: https://postgr.es/m/20200301083601.ews6hz5dduc3w2se@alap3.anarazel.de
This commit is contained in:
Andres Freund
2020-08-11 17:41:18 -07:00
parent fea10a6434
commit 3bd7f9969a
4 changed files with 191 additions and 29 deletions

View File

@ -569,3 +569,53 @@ GetNewObjectId(void)
return result;
}
#ifdef USE_ASSERT_CHECKING
/*
* Assert that xid is between [oldestXid, nextXid], which is the range we
* expect XIDs coming from tables etc to be in.
*
* As ShmemVariableCache->oldestXid could change just after this call without
* further precautions, and as a wrapped-around xid could again fall within
* the valid range, this assertion can only detect if something is definitely
* wrong, but not establish correctness.
*
* This intentionally does not expose a return value, to avoid code being
* introduced that depends on the return value.
*/
void
AssertTransactionIdInAllowableRange(TransactionId xid)
{
TransactionId oldest_xid;
TransactionId next_xid;
Assert(TransactionIdIsValid(xid));
/* we may see bootstrap / frozen */
if (!TransactionIdIsNormal(xid))
return;
/*
* We can't acquire XidGenLock, as this may be called with XidGenLock
* already held (or with other locks that don't allow XidGenLock to be
* nested). That's ok for our purposes though, since we already rely on
* 32bit reads to be atomic. While nextXid is 64 bit, we only look at
* the lower 32bit, so a skewed read doesn't hurt.
*
* There's no increased danger of falling outside [oldest, next] by
* accessing them without a lock. xid needs to have been created with
* GetNewTransactionId() in the originating session, and the locks there
* pair with the memory barrier below. We do however accept xid to be <=
* to next_xid, instead of just <, as xid could be from the procarray,
* before we see the updated nextXid value.
*/
pg_memory_barrier();
oldest_xid = ShmemVariableCache->oldestXid;
next_xid = XidFromFullTransactionId(ShmemVariableCache->nextXid);
Assert(TransactionIdFollowsOrEquals(xid, oldest_xid) ||
TransactionIdPrecedesOrEquals(xid, next_xid));
}
#endif

View File

@ -7865,8 +7865,8 @@ StartupXLOG(void)
/* also initialize latestCompletedXid, to nextXid - 1 */
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
ShmemVariableCache->latestCompletedXid = XidFromFullTransactionId(ShmemVariableCache->nextXid);
TransactionIdRetreat(ShmemVariableCache->latestCompletedXid);
ShmemVariableCache->latestCompletedXid = ShmemVariableCache->nextXid;
FullTransactionIdRetreat(&ShmemVariableCache->latestCompletedXid);
LWLockRelease(ProcArrayLock);
/*