@@ -161,7 +161,7 @@ static void SnapBuildFreeSnapshot(Snapshot snap);
161
161
162
162
static void SnapBuildSnapIncRefcount (Snapshot snap );
163
163
164
- static void SnapBuildDistributeNewCatalogSnapshot (SnapBuild * builder , XLogRecPtr lsn );
164
+ static void SnapBuildDistributeSnapshotAndInval (SnapBuild * builder , XLogRecPtr lsn , TransactionId xid );
165
165
166
166
static inline bool SnapBuildXidHasCatalogChanges (SnapBuild * builder , TransactionId xid ,
167
167
uint32 xinfo );
@@ -720,23 +720,24 @@ SnapBuildProcessNewCid(SnapBuild *builder, TransactionId xid,
720
720
}
721
721
722
722
/*
723
- * Add a new Snapshot to all transactions we're decoding that currently are
724
- * in-progress so they can see new catalog contents made by the transaction
725
- * that just committed. This is necessary because those in-progress
726
- * transactions will use the new catalog's contents from here on (at the very
727
- * least everything they do needs to be compatible with newer catalog
728
- * contents).
723
+ * Add a new Snapshot and invalidation messages to all transactions we're
724
+ * decoding that currently are in-progress so they can see new catalog contents
725
+ * made by the transaction that just committed. This is necessary because those
726
+ * in-progress transactions will use the new catalog's contents from here on
727
+ * (at the very least everything they do needs to be compatible with newer
728
+ * catalog contents).
729
729
*/
730
730
static void
731
- SnapBuildDistributeNewCatalogSnapshot (SnapBuild * builder , XLogRecPtr lsn )
731
+ SnapBuildDistributeSnapshotAndInval (SnapBuild * builder , XLogRecPtr lsn , TransactionId xid )
732
732
{
733
733
dlist_iter txn_i ;
734
734
ReorderBufferTXN * txn ;
735
735
736
736
/*
737
737
* Iterate through all toplevel transactions. This can include
738
738
* subtransactions which we just don't yet know to be that, but that's
739
- * fine, they will just get an unnecessary snapshot queued.
739
+ * fine, they will just get an unnecessary snapshot and invalidations
740
+ * queued.
740
741
*/
741
742
dlist_foreach (txn_i , & builder -> reorder -> toplevel_by_lsn )
742
743
{
@@ -749,6 +750,14 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn)
749
750
* transaction which in turn implies we don't yet need a snapshot at
750
751
* all. We'll add a snapshot when the first change gets queued.
751
752
*
753
+ * Similarly, we don't need to add invalidations to a transaction whose
754
+ * base snapshot is not yet set. Once a base snapshot is built, it will
755
+ * include the xids of committed transactions that have modified the
756
+ * catalog, thus reflecting the new catalog contents. The existing
757
+ * catalog cache will have already been invalidated after processing
758
+ * the invalidations in the transaction that modified catalogs,
759
+ * ensuring that a fresh cache is constructed during decoding.
760
+ *
752
761
* NB: This works correctly even for subtransactions because
753
762
* ReorderBufferAssignChild() takes care to transfer the base snapshot
754
763
* to the top-level transaction, and while iterating the changequeue
@@ -758,13 +767,13 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn)
758
767
continue ;
759
768
760
769
/*
761
- * We don't need to add snapshot to prepared transactions as they
762
- * should not see the new catalog contents.
770
+ * We don't need to add snapshot or invalidations to prepared
771
+ * transactions as they should not see the new catalog contents.
763
772
*/
764
773
if (rbtxn_is_prepared (txn ))
765
774
continue ;
766
775
767
- elog (DEBUG2 , "adding a new snapshot to %u at %X/%X" ,
776
+ elog (DEBUG2 , "adding a new snapshot and invalidations to %u at %X/%X" ,
768
777
txn -> xid , LSN_FORMAT_ARGS (lsn ));
769
778
770
779
/*
@@ -774,6 +783,33 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn)
774
783
SnapBuildSnapIncRefcount (builder -> snapshot );
775
784
ReorderBufferAddSnapshot (builder -> reorder , txn -> xid , lsn ,
776
785
builder -> snapshot );
786
+
787
+ /*
788
+ * Add invalidation messages to the reorder buffer of in-progress
789
+ * transactions except the current committed transaction, for which we
790
+ * will execute invalidations at the end.
791
+ *
792
+ * It is required, otherwise, we will end up using the stale catcache
793
+ * contents built by the current transaction even after its decoding,
794
+ * which should have been invalidated due to concurrent catalog
795
+ * changing transaction.
796
+ */
797
+ if (txn -> xid != xid )
798
+ {
799
+ uint32 ninvalidations ;
800
+ SharedInvalidationMessage * msgs = NULL ;
801
+
802
+ ninvalidations = ReorderBufferGetInvalidations (builder -> reorder ,
803
+ xid , & msgs );
804
+
805
+ if (ninvalidations > 0 )
806
+ {
807
+ Assert (msgs != NULL );
808
+
809
+ ReorderBufferAddInvalidations (builder -> reorder , txn -> xid , lsn ,
810
+ ninvalidations , msgs );
811
+ }
812
+ }
777
813
}
778
814
}
779
815
@@ -1045,8 +1081,11 @@ SnapBuildCommitTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid,
1045
1081
/* refcount of the snapshot builder for the new snapshot */
1046
1082
SnapBuildSnapIncRefcount (builder -> snapshot );
1047
1083
1048
- /* add a new catalog snapshot to all currently running transactions */
1049
- SnapBuildDistributeNewCatalogSnapshot (builder , lsn );
1084
+ /*
1085
+ * Add a new catalog snapshot and invalidations messages to all
1086
+ * currently running transactions.
1087
+ */
1088
+ SnapBuildDistributeSnapshotAndInval (builder , lsn , xid );
1050
1089
}
1051
1090
}
1052
1091
0 commit comments