0001-Fix-snapshot-handling-in-logicalmsg_decode-20230110.patch
text/x-patch
Filename: 0001-Fix-snapshot-handling-in-logicalmsg_decode-20230110.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0001
Subject: Fix snapshot handling in logicalmsg_decode
| File | + | − |
|---|---|---|
| src/backend/replication/logical/decode.c | 9 | 2 |
| src/backend/replication/logical/reorderbuffer.c | 9 | 0 |
From bd1b63082b23b815d26ffe1551cc4ebb9ac8a160 Mon Sep 17 00:00:00 2001 From: Tomas Vondra <tomas.vondra@postgresql.org> Date: Fri, 6 Jan 2023 17:00:43 +0100 Subject: [PATCH 1/2] Fix snapshot handling in logicalmsg_decode While decoding a transactional logical message, logicalmsg_decode might have called SnapBuildGetOrBuildSnapshot - that's incorrect, we can't build a snapshot in such case. We don't actually need the snapshot in this case (during replay we'll have the snapshot from the transaction), but in assert-enabled build this crashes. Fixed by requesting the snapshot only in non-transactional case, where we are guaranteed to have SNAPBUILD_CONSISTENT. Backpatch to 11. The issue exists since 9.6. Backpatch-through: 11 Discussion: https://postgr.es/m/84d60912-6eab-9b84-5de3-41765a5449e8@enterprisedb.com --- src/backend/replication/logical/decode.c | 11 +++++++++-- src/backend/replication/logical/reorderbuffer.c | 9 +++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c index c3bc8ecc926..4adced3b9ce 100644 --- a/src/backend/replication/logical/decode.c +++ b/src/backend/replication/logical/decode.c @@ -564,7 +564,7 @@ logicalmsg_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) TransactionId xid = XLogRecGetXid(r); uint8 info = XLogRecGetInfo(r) & ~XLR_INFO_MASK; RepOriginId origin_id = XLogRecGetOrigin(r); - Snapshot snapshot; + Snapshot snapshot = NULL; xl_logical_message *message; if (info != XLOG_LOGICAL_MESSAGE) @@ -594,7 +594,14 @@ logicalmsg_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) SnapBuildXactNeedsSkip(builder, buf->origptr))) return; - snapshot = SnapBuildGetOrBuildSnapshot(builder); + /* + * Get the snapshot we are expected to use. We only get here when we + * already have a consistent snapshot, and the change is not meant to + * be skipped. + */ + if (!message->transactional) + snapshot = SnapBuildGetOrBuildSnapshot(builder); + ReorderBufferQueueMessage(ctx->reorder, xid, snapshot, buf->endptr, message->transactional, message->message, /* first part of message is diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 29a018c58af..dbefff0b173 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -856,6 +856,12 @@ ReorderBufferQueueMessage(ReorderBuffer *rb, TransactionId xid, Assert(xid != InvalidTransactionId); + /* + * No explicit snapshot for transactional changes - we'll use a + * snapshot derived later during apply (if not skipped). + */ + Assert(!snap); + oldcontext = MemoryContextSwitchTo(rb->context); change = ReorderBufferGetChange(rb); @@ -874,6 +880,9 @@ ReorderBufferQueueMessage(ReorderBuffer *rb, TransactionId xid, ReorderBufferTXN *txn = NULL; volatile Snapshot snapshot_now = snap; + /* non-transactional changes require a valid snapshot */ + Assert(snapshot_now); + if (xid != InvalidTransactionId) txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true); -- 2.39.0