diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c index 41243d0187a..4e4e0ff42cb 100644 --- a/src/backend/replication/logical/logical.c +++ b/src/backend/replication/logical/logical.c @@ -441,6 +441,8 @@ CreateInitDecodingContext(const char *plugin, xl_routine, prepare_write, do_write, update_progress); + SetSnapBuildCreateMode(ctx->context); + /* call output plugin initialization callback */ old_context = MemoryContextSwitchTo(ctx->context); if (ctx->callbacks.startup_cb != NULL) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 7a7aba33e16..372f1934677 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -278,6 +278,15 @@ struct SnapBuild static ResourceOwner SavedResourceOwnerDuringExport = NULL; static bool ExportInProgress = false; +/* + * Used to mark the current snapbuild instance in a create mode. + * This create mode is required to prevent the snapbuilder from + * restoring a snapshot from disk to become consistent as this can + * cause the restart and confirmed flush LSNs of the slot to become + * initialized to unsafe values. + */ +static bool InCreate = false; + /* ->committed and ->catchange manipulation */ static void SnapBuildPurgeOlderTxn(SnapBuild *builder); @@ -443,6 +452,25 @@ SnapBuildSnapIncRefcount(Snapshot snap) snap->active_count++; } +/* Memory context reset callback for clearing the create mode flag */ +static void +SnapBuildResetCreateModeCallback(void *arg) +{ + InCreate = false; +} + +void +SetSnapBuildCreateMode(MemoryContext context) +{ + MemoryContextCallback *mcallback; + + mcallback = palloc0(sizeof(MemoryContextCallback)); + mcallback->func = SnapBuildResetCreateModeCallback; + MemoryContextRegisterResetCallback(context, mcallback); + + InCreate = true; +} + /* * Decrease refcount of a snapshot and free if the refcount reaches zero. * @@ -1391,8 +1419,9 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn return false; } - /* b) valid on disk state and not building full snapshot */ + /* b) valid on disk state, we are an exisiting slot, and not building full snapshot */ else if (!builder->building_full_snapshot && + !InCreate && SnapBuildRestore(builder, lsn)) { /* there won't be any state to cleanup */ diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h index f49b941b53e..3aff45dced1 100644 --- a/src/include/replication/snapbuild.h +++ b/src/include/replication/snapbuild.h @@ -64,6 +64,7 @@ extern SnapBuild *AllocateSnapshotBuilder(struct ReorderBuffer *reorder, bool need_full_snapshot, XLogRecPtr two_phase_at); extern void FreeSnapshotBuilder(SnapBuild *builder); +extern void SetSnapBuildCreateMode(MemoryContext context); extern void SnapBuildSnapDecRefcount(Snapshot snap);