@@ -1610,7 +1610,13 @@ TransactionIdIsActive(TransactionId xid)
16101610 * relations that's not required, since only backends in my own database could
16111611 * ever see the tuples in them. Also, we can ignore concurrently running lazy
16121612 * VACUUMs because (a) they must be working on other tables, and (b) they
1613- * don't need to do snapshot-based lookups.
1613+ * don't need to do snapshot-based lookups. Similarly, for the non-catalog
1614+ * horizon, we can ignore CREATE INDEX CONCURRENTLY and REINDEX CONCURRENTLY
1615+ * when they are working on non-partial, non-expressional indexes, for the
1616+ * same reasons and because they can't run in transaction blocks. (They are
1617+ * not possible to ignore for catalogs, because CIC and RC do some catalog
1618+ * operations.) Do note that this means that CIC and RC must use a lock level
1619+ * that conflicts with VACUUM.
16141620 *
16151621 * This also computes a horizon used to truncate pg_subtrans. For that
16161622 * backends in all databases have to be considered, and concurrently running
@@ -1660,9 +1666,6 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
16601666 bool in_recovery = RecoveryInProgress ();
16611667 TransactionId * other_xids = ProcGlobal -> xids ;
16621668
1663- /* inferred after ProcArrayLock is released */
1664- h -> catalog_oldest_nonremovable = InvalidTransactionId ;
1665-
16661669 LWLockAcquire (ProcArrayLock , LW_SHARED );
16671670
16681671 h -> latest_completed = ShmemVariableCache -> latestCompletedXid ;
@@ -1682,6 +1685,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
16821685
16831686 h -> oldest_considered_running = initial ;
16841687 h -> shared_oldest_nonremovable = initial ;
1688+ h -> catalog_oldest_nonremovable = initial ;
16851689 h -> data_oldest_nonremovable = initial ;
16861690
16871691 /*
@@ -1752,7 +1756,7 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
17521756 if (statusFlags & (PROC_IN_VACUUM | PROC_IN_LOGICAL_DECODING ))
17531757 continue ;
17541758
1755- /* shared tables need to take backends in all database into account */
1759+ /* shared tables need to take backends in all databases into account */
17561760 h -> shared_oldest_nonremovable =
17571761 TransactionIdOlder (h -> shared_oldest_nonremovable , xmin );
17581762
@@ -1773,11 +1777,26 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
17731777 MyDatabaseId == InvalidOid || proc -> databaseId == MyDatabaseId ||
17741778 proc -> databaseId == 0 ) /* always include WalSender */
17751779 {
1776- h -> data_oldest_nonremovable =
1777- TransactionIdOlder (h -> data_oldest_nonremovable , xmin );
1780+ /*
1781+ * We can ignore this backend if it's running CREATE INDEX
1782+ * CONCURRENTLY or REINDEX CONCURRENTLY on a "safe" index -- but
1783+ * only on vacuums of user-defined tables.
1784+ */
1785+ if (!(statusFlags & PROC_IN_SAFE_IC ))
1786+ h -> data_oldest_nonremovable =
1787+ TransactionIdOlder (h -> data_oldest_nonremovable , xmin );
1788+
1789+ /* Catalog tables need to consider all backends in this db */
1790+ h -> catalog_oldest_nonremovable =
1791+ TransactionIdOlder (h -> catalog_oldest_nonremovable , xmin );
1792+
17781793 }
17791794 }
17801795
1796+ /* catalog horizon should never be later than data */
1797+ Assert (TransactionIdPrecedesOrEquals (h -> catalog_oldest_nonremovable ,
1798+ h -> data_oldest_nonremovable ));
1799+
17811800 /*
17821801 * If in recovery fetch oldest xid in KnownAssignedXids, will be applied
17831802 * after lock is released.
@@ -1799,6 +1818,8 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
17991818 TransactionIdOlder (h -> shared_oldest_nonremovable , kaxmin );
18001819 h -> data_oldest_nonremovable =
18011820 TransactionIdOlder (h -> data_oldest_nonremovable , kaxmin );
1821+ h -> catalog_oldest_nonremovable =
1822+ TransactionIdOlder (h -> catalog_oldest_nonremovable , kaxmin );
18021823 /* temp relations cannot be accessed in recovery */
18031824 }
18041825 else
@@ -1825,6 +1846,9 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
18251846 h -> data_oldest_nonremovable =
18261847 TransactionIdRetreatedBy (h -> data_oldest_nonremovable ,
18271848 vacuum_defer_cleanup_age );
1849+ h -> catalog_oldest_nonremovable =
1850+ TransactionIdRetreatedBy (h -> catalog_oldest_nonremovable ,
1851+ vacuum_defer_cleanup_age );
18281852 /* defer doesn't apply to temp relations */
18291853 }
18301854
@@ -1847,7 +1871,9 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
18471871 h -> shared_oldest_nonremovable =
18481872 TransactionIdOlder (h -> shared_oldest_nonremovable ,
18491873 h -> slot_catalog_xmin );
1850- h -> catalog_oldest_nonremovable = h -> data_oldest_nonremovable ;
1874+ h -> catalog_oldest_nonremovable =
1875+ TransactionIdOlder (h -> catalog_oldest_nonremovable ,
1876+ h -> slot_xmin );
18511877 h -> catalog_oldest_nonremovable =
18521878 TransactionIdOlder (h -> catalog_oldest_nonremovable ,
18531879 h -> slot_catalog_xmin );
0 commit comments