@@ -476,9 +476,12 @@ ProcArrayAdd(PGPROC *proc)
476
476
(arrayP -> numProcs - index ) * sizeof (* arrayP -> pgprocnos ));
477
477
memmove (& ProcGlobal -> xids [index + 1 ], & ProcGlobal -> xids [index ],
478
478
(arrayP -> numProcs - index ) * sizeof (* ProcGlobal -> xids ));
479
+ memmove (& ProcGlobal -> vacuumFlags [index + 1 ], & ProcGlobal -> vacuumFlags [index ],
480
+ (arrayP -> numProcs - index ) * sizeof (* ProcGlobal -> vacuumFlags ));
479
481
480
482
arrayP -> pgprocnos [index ] = proc -> pgprocno ;
481
483
ProcGlobal -> xids [index ] = proc -> xid ;
484
+ ProcGlobal -> vacuumFlags [index ] = proc -> vacuumFlags ;
482
485
483
486
arrayP -> numProcs ++ ;
484
487
@@ -539,6 +542,7 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
539
542
}
540
543
541
544
Assert (TransactionIdIsValid (ProcGlobal -> xids [proc -> pgxactoff ] == 0 ));
545
+ ProcGlobal -> vacuumFlags [proc -> pgxactoff ] = 0 ;
542
546
543
547
for (index = 0 ; index < arrayP -> numProcs ; index ++ )
544
548
{
@@ -549,6 +553,8 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
549
553
(arrayP -> numProcs - index - 1 ) * sizeof (* arrayP -> pgprocnos ));
550
554
memmove (& ProcGlobal -> xids [index ], & ProcGlobal -> xids [index + 1 ],
551
555
(arrayP -> numProcs - index - 1 ) * sizeof (* ProcGlobal -> xids ));
556
+ memmove (& ProcGlobal -> vacuumFlags [index ], & ProcGlobal -> vacuumFlags [index + 1 ],
557
+ (arrayP -> numProcs - index - 1 ) * sizeof (* ProcGlobal -> vacuumFlags ));
552
558
553
559
arrayP -> pgprocnos [arrayP -> numProcs - 1 ] = -1 ; /* for debugging */
554
560
arrayP -> numProcs -- ;
@@ -626,14 +632,24 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
626
632
Assert (!TransactionIdIsValid (proc -> xid ));
627
633
628
634
proc -> lxid = InvalidLocalTransactionId ;
629
- /* must be cleared with xid/xmin: */
630
- pgxact -> vacuumFlags &= ~PROC_VACUUM_STATE_MASK ;
631
635
proc -> xmin = InvalidTransactionId ;
632
636
proc -> delayChkpt = false; /* be sure this is cleared in abort */
633
637
proc -> recoveryConflictPending = false;
634
638
635
639
Assert (pgxact -> nxids == 0 );
636
640
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
+ }
637
653
}
638
654
}
639
655
@@ -654,12 +670,18 @@ ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact,
654
670
ProcGlobal -> xids [pgxactoff ] = InvalidTransactionId ;
655
671
proc -> xid = InvalidTransactionId ;
656
672
proc -> lxid = InvalidLocalTransactionId ;
657
- /* must be cleared with xid/xmin: */
658
- pgxact -> vacuumFlags &= ~PROC_VACUUM_STATE_MASK ;
659
673
proc -> xmin = InvalidTransactionId ;
660
674
proc -> delayChkpt = false; /* be sure this is cleared in abort */
661
675
proc -> recoveryConflictPending = false;
662
676
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
+
663
685
/* Clear the subtransaction-XID cache too while holding the lock */
664
686
pgxact -> nxids = 0 ;
665
687
pgxact -> overflowed = false;
@@ -819,9 +841,8 @@ ProcArrayClearTransaction(PGPROC *proc)
819
841
proc -> xmin = InvalidTransactionId ;
820
842
proc -> recoveryConflictPending = false;
821
843
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 );
825
846
826
847
/* Clear the subtransaction-XID cache too */
827
848
pgxact -> nxids = 0 ;
@@ -1623,7 +1644,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
1623
1644
{
1624
1645
int pgprocno = arrayP -> pgprocnos [index ];
1625
1646
PGPROC * proc = & allProcs [pgprocno ];
1626
- PGXACT * pgxact = & allPgXact [ pgprocno ];
1647
+ int8 vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
1627
1648
TransactionId xid ;
1628
1649
TransactionId xmin ;
1629
1650
@@ -1640,8 +1661,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
1640
1661
*/
1641
1662
xmin = TransactionIdOlder (xmin , xid );
1642
1663
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 ))
1645
1666
continue ;
1646
1667
1647
1668
/*
@@ -1658,7 +1679,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
1658
1679
* removed, as long as pg_subtrans is not truncated) or doing logical
1659
1680
* decoding (which manages xmin separately, check below).
1660
1681
*/
1661
- if (pgxact -> vacuumFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING ))
1682
+ if (vacuumFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING ))
1662
1683
continue ;
1663
1684
1664
1685
/* shared tables need to take backends in all database into account */
@@ -1998,6 +2019,7 @@ GetSnapshotData(Snapshot snapshot)
1998
2019
size_t numProcs = arrayP -> numProcs ;
1999
2020
TransactionId * xip = snapshot -> xip ;
2000
2021
int * pgprocnos = arrayP -> pgprocnos ;
2022
+ uint8 * allVacuumFlags = ProcGlobal -> vacuumFlags ;
2001
2023
2002
2024
/*
2003
2025
* First collect set of pgxactoff/xids that need to be included in the
@@ -2007,8 +2029,6 @@ GetSnapshotData(Snapshot snapshot)
2007
2029
{
2008
2030
/* Fetch xid just once - see GetNewTransactionId */
2009
2031
TransactionId xid = UINT32_ACCESS_ONCE (other_xids [pgxactoff ]);
2010
- int pgprocno ;
2011
- PGXACT * pgxact ;
2012
2032
uint8 vacuumFlags ;
2013
2033
2014
2034
Assert (allProcs [arrayP -> pgprocnos [pgxactoff ]].pgxactoff == pgxactoff );
@@ -2044,14 +2064,11 @@ GetSnapshotData(Snapshot snapshot)
2044
2064
if (!NormalTransactionIdPrecedes (xid , xmax ))
2045
2065
continue ;
2046
2066
2047
- pgprocno = pgprocnos [pgxactoff ];
2048
- pgxact = & allPgXact [pgprocno ];
2049
- vacuumFlags = pgxact -> vacuumFlags ;
2050
-
2051
2067
/*
2052
2068
* Skip over backends doing logical decoding which manages xmin
2053
2069
* separately (check below) and ones running LAZY VACUUM.
2054
2070
*/
2071
+ vacuumFlags = allVacuumFlags [pgxactoff ];
2055
2072
if (vacuumFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM ))
2056
2073
continue ;
2057
2074
@@ -2078,6 +2095,9 @@ GetSnapshotData(Snapshot snapshot)
2078
2095
*/
2079
2096
if (!suboverflowed )
2080
2097
{
2098
+ int pgprocno = pgprocnos [pgxactoff ];
2099
+ PGXACT * pgxact = & allPgXact [pgprocno ];
2100
+
2081
2101
if (pgxact -> overflowed )
2082
2102
suboverflowed = true;
2083
2103
else
@@ -2296,11 +2316,11 @@ ProcArrayInstallImportedXmin(TransactionId xmin,
2296
2316
{
2297
2317
int pgprocno = arrayP -> pgprocnos [index ];
2298
2318
PGPROC * proc = & allProcs [pgprocno ];
2299
- PGXACT * pgxact = & allPgXact [ pgprocno ];
2319
+ int vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
2300
2320
TransactionId xid ;
2301
2321
2302
2322
/* Ignore procs running LAZY VACUUM */
2303
- if (pgxact -> vacuumFlags & PROC_IN_VACUUM )
2323
+ if (vacuumFlags & PROC_IN_VACUUM )
2304
2324
continue ;
2305
2325
2306
2326
/* We are only interested in the specific virtual transaction. */
@@ -2990,12 +3010,12 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
2990
3010
{
2991
3011
int pgprocno = arrayP -> pgprocnos [index ];
2992
3012
PGPROC * proc = & allProcs [pgprocno ];
2993
- PGXACT * pgxact = & allPgXact [ pgprocno ];
3013
+ uint8 vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
2994
3014
2995
3015
if (proc == MyProc )
2996
3016
continue ;
2997
3017
2998
- if (excludeVacuum & pgxact -> vacuumFlags )
3018
+ if (excludeVacuum & vacuumFlags )
2999
3019
continue ;
3000
3020
3001
3021
if (allDbs || proc -> databaseId == MyDatabaseId )
@@ -3410,7 +3430,7 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
3410
3430
{
3411
3431
int pgprocno = arrayP -> pgprocnos [index ];
3412
3432
PGPROC * proc = & allProcs [pgprocno ];
3413
- PGXACT * pgxact = & allPgXact [ pgprocno ];
3433
+ uint8 vacuumFlags = ProcGlobal -> vacuumFlags [ index ];
3414
3434
3415
3435
if (proc -> databaseId != databaseId )
3416
3436
continue ;
@@ -3424,7 +3444,7 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
3424
3444
else
3425
3445
{
3426
3446
(* nbackends )++ ;
3427
- if ((pgxact -> vacuumFlags & PROC_IS_AUTOVACUUM ) &&
3447
+ if ((vacuumFlags & PROC_IS_AUTOVACUUM ) &&
3428
3448
nautovacs < MAXAUTOVACPIDS )
3429
3449
autovac_pids [nautovacs ++ ] = proc -> pid ;
3430
3450
}
0 commit comments