@@ -42,6 +42,7 @@ int vacuum_defer_cleanup_age;
4242int max_standby_archive_delay = 30 * 1000 ;
4343int max_standby_streaming_delay = 30 * 1000 ;
4444bool log_recovery_conflict_waits = false;
45+ char * gp_hot_standby_snapshot_restore_point_name = NULL ;
4546
4647static HTAB * RecoveryLockLists ;
4748
@@ -55,7 +56,9 @@ static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlis
5556 uint32 wait_event_info ,
5657 bool report_waiting );
5758static void SendRecoveryConflictWithBufferPin (ProcSignalReason reason );
59+ static XLogRecPtr LogStandbySnapshotImpl (const char * rpName );
5860static XLogRecPtr LogCurrentRunningXacts (RunningTransactions CurrRunningXacts );
61+ static XLogRecPtr CbdbLogRestorePointRunningXacts (RunningTransactions CurrRunningXacts , const char * rpName );
5962static void LogAccessExclusiveLocks (int nlocks , xl_standby_lock * locks );
6063static const char * get_recovery_conflict_desc (ProcSignalReason reason );
6164
@@ -1129,6 +1132,12 @@ standby_redo(XLogReaderState *record)
11291132 }
11301133 else if (info == XLOG_RUNNING_XACTS )
11311134 {
1135+ if (EnableHotStandby && gp_hot_standby_snapshot_restore_point_name )
1136+ {
1137+ elog (LOG , "not calling redo" );
1138+ return ;
1139+ }
1140+
11321141 xl_running_xacts * xlrec = (xl_running_xacts * ) XLogRecGetData (record );
11331142 RunningTransactionsData running ;
11341143
@@ -1169,6 +1178,31 @@ standby_redo(XLogReaderState *record)
11691178 LWLockRelease (ProcArrayLock );
11701179 }
11711180 }
1181+ else if (info == XLOG_RESTORE_POINT_RUNNING_XACTS )
1182+ {
1183+ if (!gp_hot_standby_snapshot_restore_point_name )
1184+ return ;
1185+ xl_restore_point_running_xacts * xlrec =
1186+ (xl_restore_point_running_xacts * ) XLogRecGetData (record );
1187+ char * rpName = gp_hot_standby_snapshot_restore_point_name ;
1188+
1189+ if (EnableHotStandby && rpName &&
1190+ strcmp (xlrec -> rpName , rpName ) == 0 )
1191+ {
1192+ RunningTransactionsData running ;
1193+
1194+ running .xcnt = xlrec -> xcnt ;
1195+ running .subxcnt = xlrec -> subxcnt ;
1196+ running .subxid_overflow = xlrec -> subxid_overflow ;
1197+ running .nextXid = xlrec -> nextXid ;
1198+ running .latestCompletedXid = xlrec -> latestCompletedXid ;
1199+ running .oldestRunningXid = xlrec -> oldestRunningXid ;
1200+ running .xids = xlrec -> xids ;
1201+
1202+ elog (LOG , "update running xact %s" , rpName );
1203+ ProcArrayApplyRecoveryInfo (& running );
1204+ }
1205+ }
11721206 else
11731207 elog (PANIC , "standby_redo: unknown op code %u" , info );
11741208}
@@ -1241,6 +1275,12 @@ standby_redo(XLogReaderState *record)
12411275 */
12421276XLogRecPtr
12431277LogStandbySnapshot (void )
1278+ {
1279+ return LogStandbySnapshotImpl (NULL );
1280+ }
1281+
1282+ static XLogRecPtr
1283+ LogStandbySnapshotImpl (const char * rpName )
12441284{
12451285 XLogRecPtr recptr ;
12461286 RunningTransactions running ;
@@ -1278,7 +1318,15 @@ LogStandbySnapshot(void)
12781318 if (wal_level < WAL_LEVEL_LOGICAL )
12791319 LWLockRelease (ProcArrayLock );
12801320
1281- recptr = LogCurrentRunningXacts (running );
1321+ if (rpName == NULL )
1322+ {
1323+ recptr = LogCurrentRunningXacts (running );
1324+ }
1325+ else
1326+ {
1327+ recptr = CbdbLogRestorePointRunningXacts (running , rpName );
1328+ }
1329+
12821330
12831331 /* Release lock if we kept it longer ... */
12841332 if (wal_level >= WAL_LEVEL_LOGICAL )
@@ -1289,9 +1337,9 @@ LogStandbySnapshot(void)
12891337 if (IS_QUERY_DISPATCHER ())
12901338 {
12911339 /*
1292- * GPDB: write latestCompletedGxid too, because the standby needs this
1340+ * GPDB: write latestCompletedGxid too, because the standby needs this
12931341 * value for creating distributed snapshot. The standby cannot rely on
1294- * the nextGxid value to set latestCompletedGxid during restart (which
1342+ * the nextGxid value to set latestCompletedGxid during restart (which
12951343 * the primary does) because nextGxid was bumped in the checkpoint.
12961344 */
12971345 LWLockAcquire (ProcArrayLock , LW_SHARED );
@@ -1370,6 +1418,69 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
13701418 return recptr ;
13711419}
13721420
1421+ XLogRecPtr
1422+ LogRestorePointStandbySnapshot (const char * rpName )
1423+ {
1424+ return LogStandbySnapshotImpl (rpName );
1425+ }
1426+
1427+ static XLogRecPtr
1428+ CbdbLogRestorePointRunningXacts (RunningTransactions CurrRunningXacts , const char * rpName )
1429+ {
1430+ xl_restore_point_running_xacts xlrec ;
1431+ XLogRecPtr recptr ;
1432+
1433+ xlrec .xcnt = CurrRunningXacts -> xcnt ;
1434+ xlrec .subxcnt = CurrRunningXacts -> subxcnt ;
1435+ xlrec .subxid_overflow = CurrRunningXacts -> subxid_overflow ;
1436+ xlrec .nextXid = CurrRunningXacts -> nextXid ;
1437+ xlrec .oldestRunningXid = CurrRunningXacts -> oldestRunningXid ;
1438+ xlrec .latestCompletedXid = CurrRunningXacts -> latestCompletedXid ;
1439+ strlcpy (xlrec .rpName , rpName , MAXFNAMELEN );
1440+
1441+ /* Header */
1442+ XLogBeginInsert ();
1443+ XLogSetRecordFlags (XLOG_MARK_UNIMPORTANT );
1444+ XLogRegisterData ((char * ) (& xlrec ), MinSizeOfXactRpRunningXacts );
1445+
1446+ /* array of TransactionIds */
1447+ if (xlrec .xcnt > 0 )
1448+ XLogRegisterData ((char * ) CurrRunningXacts -> xids ,
1449+ (xlrec .xcnt + xlrec .subxcnt ) * sizeof (TransactionId ));
1450+
1451+ recptr = XLogInsert (RM_STANDBY_ID , XLOG_RESTORE_POINT_RUNNING_XACTS );
1452+
1453+ /* report error if subxid_overflow */
1454+ if (CurrRunningXacts -> subxid_overflow )
1455+ elog (ERROR ,
1456+ "snapshot of %u running transactions overflowed (lsn %X/%X oldest xid %u latest complete %u next xid %u)" ,
1457+ CurrRunningXacts -> xcnt ,
1458+ LSN_FORMAT_ARGS (recptr ),
1459+ CurrRunningXacts -> oldestRunningXid ,
1460+ CurrRunningXacts -> latestCompletedXid ,
1461+ CurrRunningXacts -> nextXid );
1462+ else
1463+ elog (trace_recovery (DEBUG2 ),
1464+ "snapshot of %u+%u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)" ,
1465+ CurrRunningXacts -> xcnt , CurrRunningXacts -> subxcnt ,
1466+ LSN_FORMAT_ARGS (recptr ),
1467+ CurrRunningXacts -> oldestRunningXid ,
1468+ CurrRunningXacts -> latestCompletedXid ,
1469+ CurrRunningXacts -> nextXid );
1470+
1471+ /*
1472+ * Ensure running_xacts information is synced to disk not too far in the
1473+ * future. We don't want to stall anything though (i.e. use XLogFlush()),
1474+ * so we let the wal writer do it during normal operation.
1475+ * XLogSetAsyncXactLSN() conveniently will mark the LSN as to-be-synced
1476+ * and nudge the WALWriter into action if sleeping. Check
1477+ * XLogBackgroundFlush() for details why a record might not be flushed
1478+ * without it.
1479+ */
1480+ XLogSetAsyncXactLSN (recptr );
1481+
1482+ return recptr ;
1483+ }
13731484/*
13741485 * Wholesale logging of AccessExclusiveLocks. Other lock types need not be
13751486 * logged, as described in backend/storage/lmgr/README.
0 commit comments