@@ -476,9 +476,12 @@ ProcArrayAdd(PGPROC *proc)
476476 (arrayP -> numProcs - index ) * sizeof (* arrayP -> pgprocnos ));
477477 memmove (& ProcGlobal -> xids [index + 1 ], & ProcGlobal -> xids [index ],
478478 (arrayP -> numProcs - index ) * sizeof (* ProcGlobal -> xids ));
479+ memmove (& ProcGlobal -> vacuumFlags [index + 1 ], & ProcGlobal -> vacuumFlags [index ],
480+ (arrayP -> numProcs - index ) * sizeof (* ProcGlobal -> vacuumFlags ));
479481
480482 arrayP -> pgprocnos [index ] = proc -> pgprocno ;
481483 ProcGlobal -> xids [index ] = proc -> xid ;
484+ ProcGlobal -> vacuumFlags [index ] = proc -> vacuumFlags ;
482485
483486 arrayP -> numProcs ++ ;
484487
@@ -539,6 +542,7 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
539542 }
540543
541544 Assert (TransactionIdIsValid (ProcGlobal -> xids [proc -> pgxactoff ] == 0 ));
545+ ProcGlobal -> vacuumFlags [proc -> pgxactoff ] = 0 ;
542546
543547 for (index = 0 ; index < arrayP -> numProcs ; index ++ )
544548 {
@@ -549,6 +553,8 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
549553 (arrayP -> numProcs - index - 1 ) * sizeof (* arrayP -> pgprocnos ));
550554 memmove (& ProcGlobal -> xids [index ], & ProcGlobal -> xids [index + 1 ],
551555 (arrayP -> numProcs - index - 1 ) * sizeof (* ProcGlobal -> xids ));
556+ memmove (& ProcGlobal -> vacuumFlags [index ], & ProcGlobal -> vacuumFlags [index + 1 ],
557+ (arrayP -> numProcs - index - 1 ) * sizeof (* ProcGlobal -> vacuumFlags ));
552558
553559 arrayP -> pgprocnos [arrayP -> numProcs - 1 ] = -1 ; /* for debugging */
554560 arrayP -> numProcs -- ;
@@ -626,14 +632,24 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
626632 Assert (!TransactionIdIsValid (proc -> xid ));
627633
628634 proc -> lxid = InvalidLocalTransactionId ;
629- /* must be cleared with xid/xmin: */
630- pgxact -> vacuumFlags &= ~PROC_VACUUM_STATE_MASK ;
631635 proc -> xmin = InvalidTransactionId ;
632636 proc -> delayChkpt = false; /* be sure this is cleared in abort */
633637 proc -> recoveryConflictPending = false;
634638
635639 Assert (pgxact -> nxids == 0 );
636640 Assert (pgxact -> overflowed == false);
641+
642+ /* must be cleared with xid/xmin: */
643+ /* avoid unnecessarily dirtying shared cachelines */
644+ if (proc -> vacuumFlags & PROC_VACUUM_STATE_MASK )
645+ {
646+ Assert (!LWLockHeldByMe (ProcArrayLock ));
647+ LWLockAcquire (ProcArrayLock , LW_SHARED );
648+ Assert (proc -> vacuumFlags == ProcGlobal -> vacuumFlags [proc -> pgxactoff ]);
649+ proc -> vacuumFlags &= ~PROC_VACUUM_STATE_MASK ;
650+ ProcGlobal -> vacuumFlags [proc -> pgxactoff ] = proc -> vacuumFlags ;
651+ LWLockRelease (ProcArrayLock );
652+ }
637653 }
638654}
639655
@@ -654,12 +670,18 @@ ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact,
654670 ProcGlobal -> xids [pgxactoff ] = InvalidTransactionId ;
655671 proc -> xid = InvalidTransactionId ;
656672 proc -> lxid = InvalidLocalTransactionId ;
657- /* must be cleared with xid/xmin: */
658- pgxact -> vacuumFlags &= ~PROC_VACUUM_STATE_MASK ;
659673 proc -> xmin = InvalidTransactionId ;
660674 proc -> delayChkpt = false; /* be sure this is cleared in abort */
661675 proc -> recoveryConflictPending = false;
662676
677+ /* must be cleared with xid/xmin: */
678+ /* avoid unnecessarily dirtying shared cachelines */
679+ if (proc -> vacuumFlags & PROC_VACUUM_STATE_MASK )
680+ {
681+ proc -> vacuumFlags &= ~PROC_VACUUM_STATE_MASK ;
682+ ProcGlobal -> vacuumFlags [proc -> pgxactoff ] = proc -> vacuumFlags ;
683+ }
684+
663685 /* Clear the subtransaction-XID cache too while holding the lock */
664686 pgxact -> nxids = 0 ;
665687 pgxact -> overflowed = false;
@@ -819,9 +841,8 @@ ProcArrayClearTransaction(PGPROC *proc)
819841 proc -> xmin = InvalidTransactionId ;
820842 proc -> recoveryConflictPending = false;
821843
822- /* redundant, but just in case */
823- pgxact -> vacuumFlags &= ~PROC_VACUUM_STATE_MASK ;
824- proc -> delayChkpt = false;
844+ Assert (!(proc -> vacuumFlags & PROC_VACUUM_STATE_MASK ));
845+ Assert (!proc -> delayChkpt );
825846
826847 /* Clear the subtransaction-XID cache too */
827848 pgxact -> nxids = 0 ;
@@ -1623,7 +1644,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
16231644 {
16241645 int pgprocno = arrayP -> pgprocnos [index ];
16251646 PGPROC * proc = & allProcs [pgprocno ];
1626- PGXACT * pgxact = & allPgXact [ pgprocno ];
1647+ int8 vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
16271648 TransactionId xid ;
16281649 TransactionId xmin ;
16291650
@@ -1640,8 +1661,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
16401661 */
16411662 xmin = TransactionIdOlder (xmin , xid );
16421663
1643- /* if neither is set, this proc doesn't influence the horizon */
1644- if (!TransactionIdIsValid (xmin ))
1664+ /* if neither is set, this proc doesn't influence the horizon */
1665+ if (!TransactionIdIsValid (xmin ))
16451666 continue ;
16461667
16471668 /*
@@ -1658,7 +1679,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
16581679 * removed, as long as pg_subtrans is not truncated) or doing logical
16591680 * decoding (which manages xmin separately, check below).
16601681 */
1661- if (pgxact -> vacuumFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING ))
1682+ if (vacuumFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING ))
16621683 continue ;
16631684
16641685 /* shared tables need to take backends in all database into account */
@@ -1998,6 +2019,7 @@ GetSnapshotData(Snapshot snapshot)
19982019 size_t numProcs = arrayP -> numProcs ;
19992020 TransactionId * xip = snapshot -> xip ;
20002021 int * pgprocnos = arrayP -> pgprocnos ;
2022+ uint8 * allVacuumFlags = ProcGlobal -> vacuumFlags ;
20012023
20022024 /*
20032025 * First collect set of pgxactoff/xids that need to be included in the
@@ -2007,8 +2029,6 @@ GetSnapshotData(Snapshot snapshot)
20072029 {
20082030 /* Fetch xid just once - see GetNewTransactionId */
20092031 TransactionId xid = UINT32_ACCESS_ONCE (other_xids [pgxactoff ]);
2010- int pgprocno ;
2011- PGXACT * pgxact ;
20122032 uint8 vacuumFlags ;
20132033
20142034 Assert (allProcs [arrayP -> pgprocnos [pgxactoff ]].pgxactoff == pgxactoff );
@@ -2044,14 +2064,11 @@ GetSnapshotData(Snapshot snapshot)
20442064 if (!NormalTransactionIdPrecedes (xid , xmax ))
20452065 continue ;
20462066
2047- pgprocno = pgprocnos [pgxactoff ];
2048- pgxact = & allPgXact [pgprocno ];
2049- vacuumFlags = pgxact -> vacuumFlags ;
2050-
20512067 /*
20522068 * Skip over backends doing logical decoding which manages xmin
20532069 * separately (check below) and ones running LAZY VACUUM.
20542070 */
2071+ vacuumFlags = allVacuumFlags [pgxactoff ];
20552072 if (vacuumFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM ))
20562073 continue ;
20572074
@@ -2078,6 +2095,9 @@ GetSnapshotData(Snapshot snapshot)
20782095 */
20792096 if (!suboverflowed )
20802097 {
2098+ int pgprocno = pgprocnos [pgxactoff ];
2099+ PGXACT * pgxact = & allPgXact [pgprocno ];
2100+
20812101 if (pgxact -> overflowed )
20822102 suboverflowed = true;
20832103 else
@@ -2296,11 +2316,11 @@ ProcArrayInstallImportedXmin(TransactionId xmin,
22962316 {
22972317 int pgprocno = arrayP -> pgprocnos [index ];
22982318 PGPROC * proc = & allProcs [pgprocno ];
2299- PGXACT * pgxact = & allPgXact [ pgprocno ];
2319+ int vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
23002320 TransactionId xid ;
23012321
23022322 /* Ignore procs running LAZY VACUUM */
2303- if (pgxact -> vacuumFlags & PROC_IN_VACUUM )
2323+ if (vacuumFlags & PROC_IN_VACUUM )
23042324 continue ;
23052325
23062326 /* We are only interested in the specific virtual transaction. */
@@ -2990,12 +3010,12 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
29903010 {
29913011 int pgprocno = arrayP -> pgprocnos [index ];
29923012 PGPROC * proc = & allProcs [pgprocno ];
2993- PGXACT * pgxact = & allPgXact [ pgprocno ];
3013+ uint8 vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
29943014
29953015 if (proc == MyProc )
29963016 continue ;
29973017
2998- if (excludeVacuum & pgxact -> vacuumFlags )
3018+ if (excludeVacuum & vacuumFlags )
29993019 continue ;
30003020
30013021 if (allDbs || proc -> databaseId == MyDatabaseId )
@@ -3410,7 +3430,7 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
34103430 {
34113431 int pgprocno = arrayP -> pgprocnos [index ];
34123432 PGPROC * proc = & allProcs [pgprocno ];
3413- PGXACT * pgxact = & allPgXact [ pgprocno ];
3433+ uint8 vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
34143434
34153435 if (proc -> databaseId != databaseId )
34163436 continue ;
@@ -3424,7 +3444,7 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
34243444 else
34253445 {
34263446 (* nbackends )++ ;
3427- if ((pgxact -> vacuumFlags & PROC_IS_AUTOVACUUM ) &&
3447+ if ((vacuumFlags & PROC_IS_AUTOVACUUM ) &&
34283448 nautovacs < MAXAUTOVACPIDS )
34293449 autovac_pids [nautovacs ++ ] = proc -> pid ;
34303450 }
0 commit comments