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

Commitd18c913

Browse files
committed
Rethink the delay-checkpoint-end mechanism in the back-branches.
The back-patch of commitbbace56 hadthe unfortunate effect of changing the layout of PGPROC in theback-branches, which could break extensions. This happened because itchanged the delayChkpt from type bool to type int. So, change it back,and add a new bool delayChkptEnd field instead. The new field shouldfall within what used to be padding space within the struct, and sohopefully won't cause any extensions to break.Per report from Markus Wanner and discussion with Tom Lane and others.Patch originally by me, somewhat revised by Markus Wanner per asuggestion from Michael Paquier. A very similar patch was developedby Kyotaro Horiguchi, but I failed to see the email in which that wasposted before writing one of my own.Discussion:http://postgr.es/m/CA+Tgmoao-kUD9c5nG5sub3F7tbo39+cdr8jKaOVEs_1aBWcJ3Q@mail.gmail.comDiscussion:http://postgr.es/m/20220406.164521.17171257901083417.horikyota.ntt@gmail.com
1 parent2275d04 commitd18c913

File tree

10 files changed

+109
-80
lines changed

10 files changed

+109
-80
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3071,8 +3071,8 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
30713071
* crash/basebackup, even though the state of the data directory would
30723072
* require it.
30733073
*/
3074-
Assert((MyProc->delayChkpt&DELAY_CHKPT_START)==0);
3075-
MyProc->delayChkpt|=DELAY_CHKPT_START;
3074+
Assert(!MyProc->delayChkpt);
3075+
MyProc->delayChkpt= true;
30763076

30773077
/* WAL log truncation */
30783078
WriteMTruncateXlogRec(newOldestMultiDB,
@@ -3098,7 +3098,7 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
30983098
/* Then offsets */
30993099
PerformOffsetsTruncation(oldestMulti,newOldestMulti);
31003100

3101-
MyProc->delayChkpt&= ~DELAY_CHKPT_START;
3101+
MyProc->delayChkpt= false;
31023102

31033103
END_CRIT_SECTION();
31043104
LWLockRelease(MultiXactTruncationLock);

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,9 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
476476
}
477477
pgxact->xid=xid;
478478
pgxact->xmin=InvalidTransactionId;
479-
proc->delayChkpt=0;
479+
proc->delayChkpt=false;
480480
pgxact->vacuumFlags=0;
481+
proc->delayChkptEnd= false;
481482
proc->pid=0;
482483
proc->databaseId=databaseid;
483484
proc->roleId=owner;
@@ -1170,8 +1171,8 @@ EndPrepare(GlobalTransaction gxact)
11701171

11711172
START_CRIT_SECTION();
11721173

1173-
Assert((MyProc->delayChkpt&DELAY_CHKPT_START)==0);
1174-
MyProc->delayChkpt|=DELAY_CHKPT_START;
1174+
Assert(!MyProc->delayChkpt);
1175+
MyProc->delayChkpt= true;
11751176

11761177
XLogBeginInsert();
11771178
for (record=records.head;record!=NULL;record=record->next)
@@ -1214,7 +1215,7 @@ EndPrepare(GlobalTransaction gxact)
12141215
* checkpoint starting after this will certainly see the gxact as a
12151216
* candidate for fsyncing.
12161217
*/
1217-
MyProc->delayChkpt&= ~DELAY_CHKPT_START;
1218+
MyProc->delayChkpt= false;
12181219

12191220
/*
12201221
* Remember that we have this GlobalTransaction entry locked for us. If
@@ -2287,8 +2288,8 @@ RecordTransactionCommitPrepared(TransactionId xid,
22872288
START_CRIT_SECTION();
22882289

22892290
/* See notes in RecordTransactionCommit */
2290-
Assert((MyProc->delayChkpt&DELAY_CHKPT_START)==0);
2291-
MyProc->delayChkpt|=DELAY_CHKPT_START;
2291+
Assert(!MyProc->delayChkpt);
2292+
MyProc->delayChkpt= true;
22922293

22932294
/*
22942295
* Emit the XLOG commit record. Note that we mark 2PC commits as
@@ -2336,7 +2337,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
23362337
TransactionIdCommitTree(xid,nchildren,children);
23372338

23382339
/* Checkpoint can proceed now */
2339-
MyProc->delayChkpt&= ~DELAY_CHKPT_START;
2340+
MyProc->delayChkpt= false;
23402341

23412342
END_CRIT_SECTION();
23422343

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,9 +1308,9 @@ RecordTransactionCommit(void)
13081308
* This makes checkpoint's determination of which xacts are delayChkpt
13091309
* a bit fuzzy, but it doesn't matter.
13101310
*/
1311-
Assert((MyProc->delayChkpt&DELAY_CHKPT_START)==0);
1311+
Assert(!MyProc->delayChkpt);
13121312
START_CRIT_SECTION();
1313-
MyProc->delayChkpt|=DELAY_CHKPT_START;
1313+
MyProc->delayChkpt= true;
13141314

13151315
SetCurrentTransactionStopTimestamp();
13161316

@@ -1411,7 +1411,7 @@ RecordTransactionCommit(void)
14111411
*/
14121412
if (markXidCommitted)
14131413
{
1414-
MyProc->delayChkpt&= ~DELAY_CHKPT_START;
1414+
MyProc->delayChkpt= false;
14151415
END_CRIT_SECTION();
14161416
}
14171417

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9022,27 +9022,25 @@ CreateCheckPoint(int flags)
90229022
* and we will correctly flush the update below. So we cannot miss any
90239023
* xacts we need to wait for.
90249024
*/
9025-
vxids=GetVirtualXIDsDelayingChkpt(&nvxids,DELAY_CHKPT_START);
9025+
vxids=GetVirtualXIDsDelayingChkpt(&nvxids);
90269026
if (nvxids>0)
90279027
{
90289028
do
90299029
{
90309030
pg_usleep(10000L);/* wait for 10 msec */
9031-
}while (HaveVirtualXIDsDelayingChkpt(vxids,nvxids,
9032-
DELAY_CHKPT_START));
9031+
}while (HaveVirtualXIDsDelayingChkpt(vxids,nvxids));
90339032
}
90349033
pfree(vxids);
90359034

90369035
CheckPointGuts(checkPoint.redo,flags);
90379036

9038-
vxids=GetVirtualXIDsDelayingChkpt(&nvxids,DELAY_CHKPT_COMPLETE);
9037+
vxids=GetVirtualXIDsDelayingChkptEnd(&nvxids);
90399038
if (nvxids>0)
90409039
{
90419040
do
90429041
{
90439042
pg_usleep(10000L);/* wait for 10 msec */
9044-
}while (HaveVirtualXIDsDelayingChkpt(vxids,nvxids,
9045-
DELAY_CHKPT_COMPLETE));
9043+
}while (HaveVirtualXIDsDelayingChkptEnd(vxids,nvxids));
90469044
}
90479045
pfree(vxids);
90489046

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
904904
/*
905905
* Ensure no checkpoint can change our view of RedoRecPtr.
906906
*/
907-
Assert((MyProc->delayChkpt&DELAY_CHKPT_START)!=0);
907+
Assert(MyProc->delayChkpt);
908908

909909
/*
910910
* Update RedoRecPtr so that we can make the right decision

‎src/backend/catalog/storage.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
338338
* the blocks to not exist on disk at all, but not for them to have the
339339
* wrong contents.
340340
*/
341-
Assert((MyProc->delayChkpt&DELAY_CHKPT_COMPLETE)==0);
342-
MyProc->delayChkpt |=DELAY_CHKPT_COMPLETE;
341+
Assert(!MyProc->delayChkptEnd);
342+
MyProc->delayChkptEnd= true;
343343

344344
/*
345345
* We WAL-log the truncation before actually truncating, which means
@@ -387,7 +387,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
387387
smgrtruncate(rel->rd_smgr,forks,nforks,blocks);
388388

389389
/* We've done all the critical work, so checkpoints are OK now. */
390-
MyProc->delayChkpt &= ~DELAY_CHKPT_COMPLETE;
390+
MyProc->delayChkptEnd= false;
391391

392392
/*
393393
* Update upper-level FSM pages to account for the truncation. This is

‎src/backend/storage/buffer/bufmgr.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3647,8 +3647,8 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
36473647
* essential that CreateCheckpoint waits for virtual transactions
36483648
* rather than full transactionids.
36493649
*/
3650-
Assert((MyProc->delayChkpt&DELAY_CHKPT_START)==0);
3651-
MyProc->delayChkpt|=DELAY_CHKPT_START;
3650+
Assert(!MyProc->delayChkpt);
3651+
MyProc->delayChkpt= true;
36523652
delayChkpt= true;
36533653
lsn=XLogSaveBufferForHint(buffer,buffer_std);
36543654
}
@@ -3682,7 +3682,7 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
36823682
UnlockBufHdr(bufHdr,buf_state);
36833683

36843684
if (delayChkpt)
3685-
MyProc->delayChkpt&= ~DELAY_CHKPT_START;
3685+
MyProc->delayChkpt= false;
36863686

36873687
if (dirtied)
36883688
{

‎src/backend/storage/ipc/procarray.c‎

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ static void DisplayXidCache(void);
155155
#definexc_slow_answer_inc()((void) 0)
156156
#endif/* XIDCACHE_DEBUG */
157157

158+
staticVirtualTransactionId*GetVirtualXIDsDelayingChkptGuts(int*nvxids,
159+
inttype);
160+
staticboolHaveVirtualXIDsDelayingChkptGuts(VirtualTransactionId*vxids,
161+
intnvxids,inttype);
162+
158163
/* Primitives for KnownAssignedXids array handling for standby */
159164
staticvoidKnownAssignedXidsCompress(boolforce);
160165
staticvoidKnownAssignedXidsAdd(TransactionIdfrom_xid,TransactionIdto_xid,
@@ -435,8 +440,9 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
435440
/* must be cleared with xid/xmin: */
436441
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
437442

438-
/* be sure this is cleared in abort */
439-
proc->delayChkpt=0;
443+
/* be sure these are cleared in abort */
444+
proc->delayChkpt= false;
445+
proc->delayChkptEnd= false;
440446

441447
proc->recoveryConflictPending= false;
442448

@@ -460,8 +466,9 @@ ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact,
460466
/* must be cleared with xid/xmin: */
461467
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
462468

463-
/* be sure this is cleared in abort */
464-
proc->delayChkpt=0;
469+
/* be sure these are cleared in abort */
470+
proc->delayChkpt= false;
471+
proc->delayChkptEnd= false;
465472

466473
proc->recoveryConflictPending= false;
467474

@@ -2274,26 +2281,28 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly)
22742281
}
22752282

22762283
/*
2277-
* GetVirtualXIDsDelayingChkpt -- Get the VXIDs of transactions that are
2278-
* delaying checkpoint because they have critical actions in progress.
2284+
* GetVirtualXIDsDelayingChkptGuts -- Get the VXIDs of transactions that are
2285+
* delaying the start or end of a checkpoint because they have critical
2286+
* actions in progress.
22792287
*
22802288
* Constructs an array of VXIDs of transactions that are currently in commit
2281-
* critical sections, as shown by havingspecifieddelayChkptbitsset in their
2282-
* PGPROC.
2289+
* critical sections, as shown by having delayChkptor delayChkptEndset in
2290+
*theirPGPROC.
22832291
*
22842292
* Returns a palloc'd array that should be freed by the caller.
22852293
* *nvxids is the number of valid entries.
22862294
*
2287-
* Note that because backends set or clear delayChkpt without holding any lock,
2288-
* the result is somewhat indeterminate, but we don't really care. Even in
2289-
* a multiprocessor with delayed writes to shared memory, it should be certain
2290-
* that setting of delayChkpt will propagate to shared memory when the backend
2291-
* takes a lock, so we cannot fail to see a virtual xact as delayChkpt if
2292-
* it's already inserted its commit record. Whether it takes a little while
2293-
* for clearing of delayChkpt to propagate is unimportant for correctness.
2295+
* Note that because backends set or clear delayChkpt and delayChkptEnd
2296+
* without holding any lock, the result is somewhat indeterminate, but we
2297+
* don't really care. Even in a multiprocessor with delayed writes to
2298+
* shared memory, it should be certain that setting of delayChkpt will
2299+
* propagate to shared memory when the backend takes a lock, so we cannot
2300+
* fail to see a virtual xact as delayChkpt if it's already inserted its
2301+
* commit record. Whether it takes a little while for clearing of
2302+
* delayChkpt to propagate is unimportant for correctness.
22942303
*/
2295-
VirtualTransactionId*
2296-
GetVirtualXIDsDelayingChkpt(int*nvxids,inttype)
2304+
staticVirtualTransactionId*
2305+
GetVirtualXIDsDelayingChkptGuts(int*nvxids,inttype)
22972306
{
22982307
VirtualTransactionId*vxids;
22992308
ProcArrayStruct*arrayP=procArray;
@@ -2313,7 +2322,8 @@ GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
23132322
intpgprocno=arrayP->pgprocnos[index];
23142323
PGPROC*proc=&allProcs[pgprocno];
23152324

2316-
if ((proc->delayChkpt&type)!=0)
2325+
if (((type&DELAY_CHKPT_START)&&proc->delayChkpt)||
2326+
((type&DELAY_CHKPT_COMPLETE)&&proc->delayChkptEnd))
23172327
{
23182328
VirtualTransactionIdvxid;
23192329

@@ -2329,6 +2339,26 @@ GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
23292339
returnvxids;
23302340
}
23312341

2342+
/*
2343+
* GetVirtualXIDsDelayingChkpt - Get the VXIDs of transactions that are
2344+
* delaying the start of a checkpoint.
2345+
*/
2346+
VirtualTransactionId*
2347+
GetVirtualXIDsDelayingChkpt(int*nvxids)
2348+
{
2349+
returnGetVirtualXIDsDelayingChkptGuts(nvxids,DELAY_CHKPT_START);
2350+
}
2351+
2352+
/*
2353+
* GetVirtualXIDsDelayingChkptEnd - Get the VXIDs of transactions that are
2354+
* delaying the end of a checkpoint.
2355+
*/
2356+
VirtualTransactionId*
2357+
GetVirtualXIDsDelayingChkptEnd(int*nvxids)
2358+
{
2359+
returnGetVirtualXIDsDelayingChkptGuts(nvxids,DELAY_CHKPT_COMPLETE);
2360+
}
2361+
23322362
/*
23332363
* HaveVirtualXIDsDelayingChkpt -- Are any of the specified VXIDs delaying?
23342364
*
@@ -2338,8 +2368,9 @@ GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
23382368
* Note: this is O(N^2) in the number of vxacts that are/were delaying, but
23392369
* those numbers should be small enough for it not to be a problem.
23402370
*/
2341-
bool
2342-
HaveVirtualXIDsDelayingChkpt(VirtualTransactionId*vxids,intnvxids,inttype)
2371+
staticbool
2372+
HaveVirtualXIDsDelayingChkptGuts(VirtualTransactionId*vxids,intnvxids,
2373+
inttype)
23432374
{
23442375
boolresult= false;
23452376
ProcArrayStruct*arrayP=procArray;
@@ -2357,7 +2388,8 @@ HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
23572388

23582389
GET_VXID_FROM_PGPROC(vxid,*proc);
23592390

2360-
if ((proc->delayChkpt&type)!=0&&
2391+
if ((((type&DELAY_CHKPT_START)&&proc->delayChkpt)||
2392+
((type&DELAY_CHKPT_COMPLETE)&&proc->delayChkptEnd))&&
23612393
VirtualTransactionIdIsValid(vxid))
23622394
{
23632395
inti;
@@ -2380,6 +2412,28 @@ HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
23802412
returnresult;
23812413
}
23822414

2415+
/*
2416+
* HaveVirtualXIDsDelayingChkpt -- Are any of the specified VXIDs delaying
2417+
* the start of a checkpoint?
2418+
*/
2419+
bool
2420+
HaveVirtualXIDsDelayingChkpt(VirtualTransactionId*vxids,intnvxids)
2421+
{
2422+
returnHaveVirtualXIDsDelayingChkptGuts(vxids,nvxids,
2423+
DELAY_CHKPT_START);
2424+
}
2425+
2426+
/*
2427+
* HaveVirtualXIDsDelayingChkptEnd -- Are any of the specified VXIDs delaying
2428+
* the end of a checkpoint?
2429+
*/
2430+
bool
2431+
HaveVirtualXIDsDelayingChkptEnd(VirtualTransactionId*vxids,intnvxids)
2432+
{
2433+
returnHaveVirtualXIDsDelayingChkptGuts(vxids,nvxids,
2434+
DELAY_CHKPT_COMPLETE);
2435+
}
2436+
23832437
/*
23842438
* BackendPidGetProc -- get a backend's PGPROC given its PID
23852439
*

‎src/include/storage/proc.h‎

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -84,36 +84,8 @@ struct XidCache
8484
#defineINVALID_PGPROCNOPG_INT32_MAX
8585

8686
/*
87-
* Flags for PGPROC.delayChkpt
88-
*
89-
* These flags can be used to delay the start or completion of a checkpoint
90-
* for short periods. A flag is in effect if the corresponding bit is set in
91-
* the PGPROC of any backend.
92-
*
93-
* For our purposes here, a checkpoint has three phases: (1) determine the
94-
* location to which the redo pointer will be moved, (2) write all the
95-
* data durably to disk, and (3) WAL-log the checkpoint.
96-
*
97-
* Setting DELAY_CHKPT_START prevents the system from moving from phase 1
98-
* to phase 2. This is useful when we are performing a WAL-logged modification
99-
* of data that will be flushed to disk in phase 2. By setting this flag
100-
* before writing WAL and clearing it after we've both written WAL and
101-
* performed the corresponding modification, we ensure that if the WAL record
102-
* is inserted prior to the new redo point, the corresponding data changes will
103-
* also be flushed to disk before the checkpoint can complete. (In the
104-
* extremely common case where the data being modified is in shared buffers
105-
* and we acquire an exclusive content lock on the relevant buffers before
106-
* writing WAL, this mechanism is not needed, because phase 2 will block
107-
* until we release the content lock and then flush the modified data to
108-
* disk.)
109-
*
110-
* Setting DELAY_CHKPT_COMPLETE prevents the system from moving from phase 2
111-
* to phase 3. This is useful if we are performing a WAL-logged operation that
112-
* might invalidate buffers, such as relation truncation. In this case, we need
113-
* to ensure that any buffers which were invalidated and thus not flushed by
114-
* the checkpoint are actaully destroyed on disk. Replay can cope with a file
115-
* or block that doesn't exist, but not with a block that has the wrong
116-
* contents.
87+
* Flags used only for type of internal functions
88+
* GetVirtualXIDsDelayingChkptGuts and HaveVirtualXIDsDelayingChkptGuts.
11789
*/
11890
#defineDELAY_CHKPT_START(1<<0)
11991
#defineDELAY_CHKPT_COMPLETE(1<<1)
@@ -184,7 +156,8 @@ struct PGPROC
184156
LOCKMASKheldLocks;/* bitmask for lock types already held on this
185157
* lock object by this backend */
186158

187-
intdelayChkpt;/* for DELAY_CHKPT_* flags */
159+
booldelayChkpt;/* true if this proc delays checkpoint start */
160+
booldelayChkptEnd;/* true if this proc delays checkpoint end */
188161

189162
/*
190163
* Info to allow us to wait for synchronous replication, if needed.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp