summaryrefslogtreecommitdiff
path: root/src/backend/replication/logical/decode.c
diff options
context:
space:
mode:
authorTomas Vondra <tomas.vondra@postgresql.org>2023-02-22 15:24:09 +0100
committerTomas Vondra <tomas.vondra@postgresql.org>2023-02-22 16:25:45 +0100
commit8b9cbd42b61ff55e5519631bada5d310159e3a5f (patch)
tree407843fdfe9fa116f03a7a5d04db1cc0a39488a7 /src/backend/replication/logical/decode.c
parent482ab3e4f9e0a2fcef96bdcbe7a719858fae8f79 (diff)
Fix snapshot handling in logicalmsg_decode
Whe decoding a transactional logical message, logicalmsg_decode called SnapBuildGetOrBuildSnapshot. But we may not have a consistent snapshot yet at that point. We don't actually need the snapshot in this case (during replay we'll have the snapshot from the transaction), so in practice this is harmless. 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 Reviewed-by: Andres Freund Discussion: https://postgr.es/m/84d60912-6eab-9b84-5de3-41765a5449e8@enterprisedb.com
Diffstat (limited to 'src/backend/replication/logical/decode.c')
-rw-r--r--src/backend/replication/logical/decode.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index 54efe2e4b44..1c0058fc8fd 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -628,7 +628,7 @@ DecodeLogicalMsgOp(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)
@@ -658,7 +658,17 @@ DecodeLogicalMsgOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
SnapBuildXactNeedsSkip(builder, buf->origptr)))
return;
- snapshot = SnapBuildGetOrBuildSnapshot(builder, xid);
+ /*
+ * If this is a non-transactional change, get the snapshot we're expected
+ * to use. We only get here when the snapshot is consistent, and the
+ * change is not meant to be skipped.
+ *
+ * For transactional changes we don't need a snapshot, we'll use the
+ * regular snapshot maintained by ReorderBuffer. We just leave it NULL.
+ */
+ if (!message->transactional)
+ snapshot = SnapBuildGetOrBuildSnapshot(builder, xid);
+
ReorderBufferQueueMessage(ctx->reorder, xid, snapshot, buf->endptr,
message->transactional,
message->message, /* first part of message is