8000 Don't use on-disk snapshots for exported logical decoding snapshot. · anrs/postgres@54270d7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 54270d7

Browse files
committed
Don't use on-disk snapshots for exported logical decoding snapshot.
Logical decoding stores historical snapshots on disk, so that logical decoding can restart without having to reconstruct a snapshot from scratch (for which the resources are not guaranteed to be present anymore). These serialized snapshots were also used when creating a new slot via the walsender interface, which can export a "full" snapshot (i.e. one that can read all tables, not just catalog ones). The problem is that the serialized snapshots are only useful for catalogs and not for normal user tables. Thus the use of such a serialized snapshot could result in an inconsistent snapshot being exported, which could lead to queries returning wrong data. This would only happen if logical slots are created while another logical slot already exists. Author: Petr Jelinek Reviewed-By: Andres Freund Discussion: https://postgr.es/m/f37e975c-908f-858e-707f-058d3b1eb214@2ndquadrant.com Backport: 9.4, where logical decoding was introduced.
1 parent 47f896b commit 54270d7

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

src/backend/replication/logical/logical.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ static LogicalDecodingContext *
111111
StartupDecodingContext(List *output_plugin_options,
112112
XLogRecPtr start_lsn,
113113
TransactionId xmin_horizon,
114+
bool need_full_snapshot,
114115
XLogPageReadCB read_page,
115116
LogicalOutputPluginWriterPrepareWrite prepare_write,
116117
LogicalOutputPluginWriterWrite do_write)
@@ -170,7 +171,8 @@ StartupDecodingContext(List *output_plugin_options,
170171

171172
ctx->reorder = ReorderBufferAllocate();
172173
ctx->snapshot_builder =
173-
AllocateSnapshotBuilder(ctx->reorder, xmin_horizon, start_lsn);
174+
AllocateSnapshotBuilder(ctx->reorder, xmin_horizon, start_lsn,
175+
need_full_snapshot);
174176

175177
ctx->reorder->private_data = ctx;
176178

@@ -340,7 +342,8 @@ CreateInitDecodingContext(char *plugin,
340342
ReplicationSlotSave();
341343

342344
ctx = StartupDecodingContext(NIL, InvalidXLogRecPtr, xmin_horizon,
343-
read_page, prepare_write, do_write);
345+
need_full_snapshot, read_page, prepare_write,
346+
do_write);
344347

345348
/* call output plugin initialization callback */
346349
old_context = MemoryContextSwitchTo(ctx->context);
@@ -421,7 +424,7 @@ CreateDecodingContext(XLogRecPtr start_lsn,
421424
}
422425

423426
ctx = StartupDecodingContext(output_plugin_options,
424-
start_lsn, InvalidTransactionId,
427+
start_lsn, InvalidTransactionId, false,
425428
read_page, prepare_write, do_write);
426429

427430
/* call output plugin initialization callback */

src/backend/replication/logical/snapbuild.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ struct SnapBuild
164164
*/
165165
TransactionId initial_xmin_horizon;
166166

167+
/* Indicates if we are building full snapshot or just catalog one .*/
168+
bool building_full_snapshot;
169+
167170
/*
168171
* Snapshot that's valid to see the catalog state seen at this moment.
169172
*/
@@ -280,7 +283,8 @@ static bool SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn);
280283
SnapBuild *
281284
AllocateSnapshotBuilder(ReorderBuffer *reorder,
282285
TransactionId xmin_horizon,
283-
XLogRecPtr start_lsn)
286+
XLogRecPtr start_lsn,
287+
bool need_full_snapshot)
284288
{
285289
MemoryContext context;
286290
MemoryContext oldcontext;
@@ -309,6 +313,7 @@ AllocateSnapshotBuilder(ReorderBuffer *reorder,
309313

310314
builder->initial_xmin_horizon = xmin_horizon;
311315
builder->start_decoding_at = start_lsn;
316+
builder->building_full_snapshot = need_full_snapshot;
312317

313318
MemoryContextSwitchTo(oldcontext);
314319

@@ -1210,7 +1215,7 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
12101215
*
12111216
* a) There were no running transactions when the xl_running_xacts record
12121217
* was inserted, jump to CONSISTENT immediately. We might find such a
1213-
* state we were waiting for b) and c).
1218+
* state we were waiting for b) or c).
12141219
*
12151220
* b) Wait for all toplevel transactions that were running to end. We
12161221
* simply track the number of in-progress toplevel transactions and
@@ -1225,7 +1230,10 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
12251230
* at all.
12261231
*
12271232
* c) This (in a previous run) or another decoding slot serialized a
1228-
* snapshot to disk that we can use.
1233+
* snapshot to disk that we can use. Can't use this method for the
1234+
* initial snapshot when slot is being created and needs full snapshot
1235+
* for export or direct use, as that snapshot will only contain catalog
1236+
* modifying transactions.
12291237
* ---
12301238
*/
12311239

@@ -1280,8 +1288,9 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
12801288

12811289
return false;
12821290
}
1283-
/* c) valid on disk state */
1284-
else if (SnapBuildRestore(builder, lsn))
1291+
/* c) valid on disk state and not building full snapshot */
1292+
else if (!builder->building_full_snapshot &&
1293+
SnapBuildRestore(builder, lsn))
12851294
{
12861295
/* there won't be any state to cleanup */
12871296
return false;

src/include/replication/snapbuild.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ struct xl_running_xacts;
5454
extern void CheckPointSnapBuild(void);
5555

5656
extern SnapBuild *AllocateSnapshotBuilder(struct ReorderBuffer *cache,
57-
TransactionId xmin_horizon, XLogRecPtr start_lsn);
57+
TransactionId xmin_horizon, XLogRecPtr start_lsn,
58+
bool need_full_snapshot);
5859
extern void FreeSnapshotBuilder(SnapBuild *cache);
5960

6061
extern void SnapBuildSnapDecRefcount(Snapshot snap);

0 commit comments

Comments
 (0)
0