Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2fc7af5

Browse files
committed
Add basic infrastructure for 64 bit transaction IDs.
Instead of inferring epoch progress from xids and checkpoints,introduce a 64 bit FullTransactionId type and use it to track xidgeneration. This fixes an unlikely bug where the epoch is reportedincorrectly if the range of active xids wraps around more than oncebetween checkpoints.The only user-visible effect of this commit is to correct the epochused by txid_current() and txid_status(), also visible withpg_controldata, in those rare circumstances. It also creates somebasic infrastructure so that later patches can use 64 bittransaction IDs in more places.The new type is a struct that we pass by value, as a form of strongtypedef. This prevents the sort of accidental confusion betweenTransactionId and FullTransactionId that would be possible if wewere to use a plain old uint64.Author: Thomas MunroReported-by: Amit KapilaReviewed-by: Andres Freund, Tom Lane, Heikki LinnakangasDiscussion:https://postgr.es/m/CAA4eK1%2BMv%2Bmb0HFfWM9Srtc6MVe160WFurXV68iAFMcagRZ0dQ%40mail.gmail.com
1 parent2a96909 commit2fc7af5

File tree

24 files changed

+224
-238
lines changed

24 files changed

+224
-238
lines changed

‎src/backend/access/rmgrdesc/xlogdesc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515
#include"postgres.h"
1616

17+
#include"access/transam.h"
1718
#include"access/xlog.h"
1819
#include"access/xlog_internal.h"
1920
#include"catalog/pg_control.h"
@@ -52,7 +53,8 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
5253
checkpoint->ThisTimeLineID,
5354
checkpoint->PrevTimeLineID,
5455
checkpoint->fullPageWrites ?"true" :"false",
55-
checkpoint->nextXidEpoch,checkpoint->nextXid,
56+
EpochFromFullTransactionId(checkpoint->nextFullXid),
57+
XidFromFullTransactionId(checkpoint->nextFullXid),
5658
checkpoint->nextOid,
5759
checkpoint->nextMulti,
5860
checkpoint->nextMultiOffset,

‎src/backend/access/transam/clog.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,12 +749,12 @@ ZeroCLOGPage(int pageno, bool writeXlog)
749749

750750
/*
751751
* This must be called ONCE during postmaster or standalone-backend startup,
752-
* after StartupXLOG has initialized ShmemVariableCache->nextXid.
752+
* after StartupXLOG has initialized ShmemVariableCache->nextFullXid.
753753
*/
754754
void
755755
StartupCLOG(void)
756756
{
757-
TransactionIdxid=ShmemVariableCache->nextXid;
757+
TransactionIdxid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
758758
intpageno=TransactionIdToPage(xid);
759759

760760
LWLockAcquire(CLogControlLock,LW_EXCLUSIVE);
@@ -773,7 +773,7 @@ StartupCLOG(void)
773773
void
774774
TrimCLOG(void)
775775
{
776-
TransactionIdxid=ShmemVariableCache->nextXid;
776+
TransactionIdxid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
777777
intpageno=TransactionIdToPage(xid);
778778

779779
LWLockAcquire(CLogControlLock,LW_EXCLUSIVE);
@@ -792,7 +792,7 @@ TrimCLOG(void)
792792
* but makes no WAL entry). Let's just be safe. (We need not worry about
793793
* pages beyond the current one, since those will be zeroed when first
794794
* used. For the same reason, there is no need to do anything when
795-
*nextXid is exactly at a page boundary; and it's likely that the
795+
*nextFullXid is exactly at a page boundary; and it's likely that the
796796
* "current" page doesn't exist yet in that case.)
797797
*/
798798
if (TransactionIdToPgIndex(xid)!=0)

‎src/backend/access/transam/commit_ts.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ ZeroCommitTsPage(int pageno, bool writeXlog)
553553

554554
/*
555555
* This must be called ONCE during postmaster or standalone-backend startup,
556-
* after StartupXLOG has initialized ShmemVariableCache->nextXid.
556+
* after StartupXLOG has initialized ShmemVariableCache->nextFullXid.
557557
*/
558558
void
559559
StartupCommitTs(void)
@@ -643,7 +643,7 @@ ActivateCommitTs(void)
643643
}
644644
LWLockRelease(CommitTsLock);
645645

646-
xid=ShmemVariableCache->nextXid;
646+
xid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
647647
pageno=TransactionIdToCTsPage(xid);
648648

649649
/*

‎src/backend/access/transam/multixact.c

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3267,9 +3267,9 @@ multixact_redo(XLogReaderState *record)
32673267
xlrec->moff+xlrec->nmembers);
32683268

32693269
/*
3270-
* Make surenextXid is beyond any XID mentioned in the record. This
3271-
* should be unnecessary, since any XID found here ought to have other
3272-
* evidence in the XLOG, but let's be safe.
3270+
* Make surenextFullXid is beyond any XID mentioned in the record.
3271+
*Thisshould be unnecessary, since any XID found here ought to have
3272+
*otherevidence in the XLOG, but let's be safe.
32733273
*/
32743274
max_xid=XLogRecGetXid(record);
32753275
for (i=0;i<xlrec->nmembers;i++)
@@ -3278,19 +3278,7 @@ multixact_redo(XLogReaderState *record)
32783278
max_xid=xlrec->members[i].xid;
32793279
}
32803280

3281-
/*
3282-
* We don't expect anyone else to modify nextXid, hence startup
3283-
* process doesn't need to hold a lock while checking this. We still
3284-
* acquire the lock to modify it, though.
3285-
*/
3286-
if (TransactionIdFollowsOrEquals(max_xid,
3287-
ShmemVariableCache->nextXid))
3288-
{
3289-
LWLockAcquire(XidGenLock,LW_EXCLUSIVE);
3290-
ShmemVariableCache->nextXid=max_xid;
3291-
TransactionIdAdvance(ShmemVariableCache->nextXid);
3292-
LWLockRelease(XidGenLock);
3293-
}
3281+
AdvanceNextFullTransactionIdPastXid(max_xid);
32943282
}
32953283
elseif (info==XLOG_MULTIXACT_TRUNCATE_ID)
32963284
{

‎src/backend/access/transam/subtrans.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,15 @@ ZeroSUBTRANSPage(int pageno)
241241

242242
/*
243243
* This must be called ONCE during postmaster or standalone-backend startup,
244-
* after StartupXLOG has initialized ShmemVariableCache->nextXid.
244+
* after StartupXLOG has initialized ShmemVariableCache->nextFullXid.
245245
*
246-
* oldestActiveXID is the oldest XID of any prepared transaction, ornextXid
246+
* oldestActiveXID is the oldest XID of any prepared transaction, ornextFullXid
247247
* if there are none.
248248
*/
249249
void
250250
StartupSUBTRANS(TransactionIdoldestActiveXID)
251251
{
252+
FullTransactionIdnextFullXid;
252253
intstartPage;
253254
intendPage;
254255

@@ -261,7 +262,8 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
261262
LWLockAcquire(SubtransControlLock,LW_EXCLUSIVE);
262263

263264
startPage=TransactionIdToPage(oldestActiveXID);
264-
endPage=TransactionIdToPage(ShmemVariableCache->nextXid);
265+
nextFullXid=ShmemVariableCache->nextFullXid;
266+
endPage=TransactionIdToPage(XidFromFullTransactionId(nextFullXid));
265267

266268
while (startPage!=endPage)
267269
{

‎src/backend/access/transam/twophase.c

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,16 +1878,16 @@ restoreTwoPhaseData(void)
18781878
*
18791879
* Scan the shared memory entries of TwoPhaseState and determine the range
18801880
* of valid XIDs present. This is run during database startup, after we
1881-
* have completed reading WAL. ShmemVariableCache->nextXid has been set to
1881+
* have completed reading WAL. ShmemVariableCache->nextFullXid has been set to
18821882
* one more than the highest XID for which evidence exists in WAL.
18831883
*
1884-
* We throw away any prepared xacts with main XID beyondnextXid --- if any
1884+
* We throw away any prepared xacts with main XID beyondnextFullXid --- if any
18851885
* are present, it suggests that the DBA has done a PITR recovery to an
18861886
* earlier point in time without cleaning out pg_twophase. We dare not
18871887
* try to recover such prepared xacts since they likely depend on database
18881888
* state that doesn't exist now.
18891889
*
1890-
* However, we will advancenextXid beyond any subxact XIDs belonging to
1890+
* However, we will advancenextFullXid beyond any subxact XIDs belonging to
18911891
* valid prepared xacts. We need to do this since subxact commit doesn't
18921892
* write a WAL entry, and so there might be no evidence in WAL of those
18931893
* subxact XIDs.
@@ -1897,7 +1897,7 @@ restoreTwoPhaseData(void)
18971897
* backup should be rolled in.
18981898
*
18991899
* Our other responsibility is to determine and return the oldest valid XID
1900-
* among the prepared xacts (if none, return ShmemVariableCache->nextXid).
1900+
* among the prepared xacts (if none, return ShmemVariableCache->nextFullXid).
19011901
* This is needed to synchronize pg_subtrans startup properly.
19021902
*
19031903
* If xids_p and nxids_p are not NULL, pointer to a palloc'd array of all
@@ -1907,7 +1907,8 @@ restoreTwoPhaseData(void)
19071907
TransactionId
19081908
PrescanPreparedTransactions(TransactionId**xids_p,int*nxids_p)
19091909
{
1910-
TransactionIdorigNextXid=ShmemVariableCache->nextXid;
1910+
FullTransactionIdnextFullXid=ShmemVariableCache->nextFullXid;
1911+
TransactionIdorigNextXid=XidFromFullTransactionId(nextFullXid);
19111912
TransactionIdresult=origNextXid;
19121913
TransactionId*xids=NULL;
19131914
intnxids=0;
@@ -2123,7 +2124,7 @@ RecoverPreparedTransactions(void)
21232124
*
21242125
* If setParent is true, set up subtransaction parent linkages.
21252126
*
2126-
* If setNextXid is true, set ShmemVariableCache->nextXid to the newest
2127+
* If setNextXid is true, set ShmemVariableCache->nextFullXid to the newest
21272128
* value scanned.
21282129
*/
21292130
staticchar*
@@ -2132,7 +2133,8 @@ ProcessTwoPhaseBuffer(TransactionId xid,
21322133
boolfromdisk,
21332134
boolsetParent,boolsetNextXid)
21342135
{
2135-
TransactionIdorigNextXid=ShmemVariableCache->nextXid;
2136+
FullTransactionIdnextFullXid=ShmemVariableCache->nextFullXid;
2137+
TransactionIdorigNextXid=XidFromFullTransactionId(nextFullXid);
21362138
TransactionId*subxids;
21372139
char*buf;
21382140
TwoPhaseFileHeader*hdr;
@@ -2212,7 +2214,7 @@ ProcessTwoPhaseBuffer(TransactionId xid,
22122214

22132215
/*
22142216
* Examine subtransaction XIDs ... they should all follow main XID, and
2215-
* they may force us to advancenextXid.
2217+
* they may force us to advancenextFullXid.
22162218
*/
22172219
subxids= (TransactionId*) (buf+
22182220
MAXALIGN(sizeof(TwoPhaseFileHeader))+
@@ -2223,25 +2225,9 @@ ProcessTwoPhaseBuffer(TransactionId xid,
22232225

22242226
Assert(TransactionIdFollows(subxid,xid));
22252227

2226-
/* update nextXid if needed */
2227-
if (setNextXid&&
2228-
TransactionIdFollowsOrEquals(subxid,
2229-
ShmemVariableCache->nextXid))
2230-
{
2231-
/*
2232-
* We don't expect anyone else to modify nextXid, hence we don't
2233-
* need to hold a lock while examining it. We still acquire the
2234-
* lock to modify it, though, so we recheck.
2235-
*/
2236-
LWLockAcquire(XidGenLock,LW_EXCLUSIVE);
2237-
if (TransactionIdFollowsOrEquals(subxid,
2238-
ShmemVariableCache->nextXid))
2239-
{
2240-
ShmemVariableCache->nextXid=subxid;
2241-
TransactionIdAdvance(ShmemVariableCache->nextXid);
2242-
}
2243-
LWLockRelease(XidGenLock);
2244-
}
2228+
/* update nextFullXid if needed */
2229+
if (setNextXid)
2230+
AdvanceNextFullTransactionIdPastXid(subxid);
22452231

22462232
if (setParent)
22472233
SubTransSetParent(subxid,xid);

‎src/backend/access/transam/varsup.c

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ GetNewTransactionId(bool isSubXact)
7373

7474
LWLockAcquire(XidGenLock,LW_EXCLUSIVE);
7575

76-
xid=ShmemVariableCache->nextXid;
76+
xid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
7777

7878
/*----------
7979
* Check to see if it's safe to assign another XID. This protects against
@@ -156,7 +156,7 @@ GetNewTransactionId(bool isSubXact)
156156

157157
/* Re-acquire lock and start over */
158158
LWLockAcquire(XidGenLock,LW_EXCLUSIVE);
159-
xid=ShmemVariableCache->nextXid;
159+
xid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
160160
}
161161

162162
/*
@@ -173,12 +173,12 @@ GetNewTransactionId(bool isSubXact)
173173
ExtendSUBTRANS(xid);
174174

175175
/*
176-
* Now advance thenextXid counter. This must not happen until after we
177-
* have successfully completed ExtendCLOG() --- if that routine fails, we
178-
* want the next incoming transaction to try it again. We cannot assign
179-
* more XIDs until there is CLOG space for them.
176+
* Now advance thenextFullXid counter. This must not happen until after
177+
*wehave successfully completed ExtendCLOG() --- if that routine fails,
178+
*wewant the next incoming transaction to try it again. We cannot
179+
*assignmore XIDs until there is CLOG space for them.
180180
*/
181-
TransactionIdAdvance(ShmemVariableCache->nextXid);
181+
FullTransactionIdAdvance(&ShmemVariableCache->nextFullXid);
182182

183183
/*
184184
* We must store the new XID into the shared ProcArray before releasing
@@ -236,18 +236,64 @@ GetNewTransactionId(bool isSubXact)
236236
}
237237

238238
/*
239-
* ReadnextXid but don't allocate it.
239+
* ReadnextFullXid but don't allocate it.
240240
*/
241-
TransactionId
242-
ReadNewTransactionId(void)
241+
FullTransactionId
242+
ReadNextFullTransactionId(void)
243243
{
244-
TransactionIdxid;
244+
FullTransactionIdfullXid;
245245

246246
LWLockAcquire(XidGenLock,LW_SHARED);
247-
xid=ShmemVariableCache->nextXid;
247+
fullXid=ShmemVariableCache->nextFullXid;
248248
LWLockRelease(XidGenLock);
249249

250-
returnxid;
250+
returnfullXid;
251+
}
252+
253+
/*
254+
* Advance nextFullXid to the value after a given xid. The epoch is inferred.
255+
* This must only be called during recovery or from two-phase start-up code.
256+
*/
257+
void
258+
AdvanceNextFullTransactionIdPastXid(TransactionIdxid)
259+
{
260+
FullTransactionIdnewNextFullXid;
261+
TransactionIdnext_xid;
262+
uint32epoch;
263+
264+
/*
265+
* It is safe to read nextFullXid without a lock, because this is only
266+
* called from the startup process or single-process mode, meaning that no
267+
* other process can modify it.
268+
*/
269+
Assert(AmStartupProcess()|| !IsUnderPostmaster);
270+
271+
/* Fast return if this isn't an xid high enough to move the needle. */
272+
next_xid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
273+
if (!TransactionIdFollowsOrEquals(xid,next_xid))
274+
return;
275+
276+
/*
277+
* Compute the FullTransactionId that comes after the given xid. To do
278+
* this, we preserve the existing epoch, but detect when we've wrapped
279+
* into a new epoch. This is necessary because WAL records and 2PC state
280+
* currently contain 32 bit xids. The wrap logic is safe in those cases
281+
* because the span of active xids cannot exceed one epoch at any given
282+
* point in the WAL stream.
283+
*/
284+
TransactionIdAdvance(xid);
285+
epoch=EpochFromFullTransactionId(ShmemVariableCache->nextFullXid);
286+
if (unlikely(xid<next_xid))
287+
++epoch;
288+
newNextFullXid=FullTransactionIdFromEpochAndXid(epoch,xid);
289+
290+
/*
291+
* We still need to take a lock to modify the value when there are
292+
* concurrent readers.
293+
*/
294+
LWLockAcquire(XidGenLock,LW_EXCLUSIVE);
295+
ShmemVariableCache->nextFullXid=newNextFullXid;
296+
LWLockRelease(XidGenLock);
251297
}
252298

253299
/*
@@ -351,7 +397,7 @@ SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
351397
ShmemVariableCache->xidStopLimit=xidStopLimit;
352398
ShmemVariableCache->xidWrapLimit=xidWrapLimit;
353399
ShmemVariableCache->oldestXidDB=oldest_datoid;
354-
curXid=ShmemVariableCache->nextXid;
400+
curXid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
355401
LWLockRelease(XidGenLock);
356402

357403
/* Log the info */
@@ -427,7 +473,7 @@ ForceTransactionIdLimitUpdate(void)
427473

428474
/* Locking is probably not really necessary, but let's be careful */
429475
LWLockAcquire(XidGenLock,LW_SHARED);
430-
nextXid=ShmemVariableCache->nextXid;
476+
nextXid=XidFromFullTransactionId(ShmemVariableCache->nextFullXid);
431477
xidVacLimit=ShmemVariableCache->xidVacLimit;
432478
oldestXid=ShmemVariableCache->oldestXid;
433479
oldestXidDB=ShmemVariableCache->oldestXidDB;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp