aboutsummaryrefslogtreecommitdiff
path: root/src/backend/replication/logical/decode.c
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2024-10-25 06:51:02 -0700
committerNoah Misch <noah@leadboat.com>2024-10-25 06:51:07 -0700
commite3914bd136e467b3af7e5a334e0e753df2a13f53 (patch)
treea51b677d3044786f0988db46bf9945d76f3bc2a4 /src/backend/replication/logical/decode.c
parentdca68242a81b39672557b77c72ce15790bf0f7fe (diff)
downloadpostgresql-e3914bd136e467b3af7e5a334e0e753df2a13f53.tar.gz
postgresql-e3914bd136e467b3af7e5a334e0e753df2a13f53.zip
For inplace update, send nontransactional invalidations.
The inplace update survives ROLLBACK. The inval didn't, so another backend's DDL could then update the row without incorporating the inplace update. In the test this fixes, a mix of CREATE INDEX and ALTER TABLE resulted in a table with an index, yet relhasindex=f. That is a source of index corruption. Back-patch to v12 (all supported versions). The back branch versions don't change WAL, because those branches just added end-of-recovery SIResetAll(). All branches change the ABI of extern function PrepareToInvalidateCacheTuple(). No PGXN extension calls that, and there's no apparent use case in extensions. Reviewed by Nitin Motiani and (in earlier versions) Andres Freund. Discussion: https://postgr.es/m/20240523000548.58.nmisch@google.com
Diffstat (limited to 'src/backend/replication/logical/decode.c')
-rw-r--r--src/backend/replication/logical/decode.c26
1 files changed, 11 insertions, 15 deletions
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index 1c0058fc8fd..e1753dd7d53 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -547,23 +547,19 @@ DecodeHeapOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
/*
* Inplace updates are only ever performed on catalog tuples and
- * can, per definition, not change tuple visibility. Since we
- * don't decode catalog tuples, we're not interested in the
- * record's contents.
+ * can, per definition, not change tuple visibility. Inplace
+ * updates don't affect storage or interpretation of table rows,
+ * so they don't affect logicalrep_write_tuple() outcomes. Hence,
+ * we don't process invalidations from the original operation. If
+ * inplace updates did affect those things, invalidations wouldn't
+ * make it work, since there are no snapshot-specific versions of
+ * inplace-updated values. Since we also don't decode catalog
+ * tuples, we're not interested in the record's contents.
*
- * In-place updates can be used either by XID-bearing transactions
- * (e.g. in CREATE INDEX CONCURRENTLY) or by XID-less
- * transactions (e.g. VACUUM). In the former case, the commit
- * record will include cache invalidations, so we mark the
- * transaction as catalog modifying here. Currently that's
- * redundant because the commit will do that as well, but once we
- * support decoding in-progress relations, this will be important.
+ * WAL contains likely-unnecessary commit-time invals from the
+ * CacheInvalidateHeapTuple() call in heap_inplace_update().
+ * Excess invalidation is safe.
*/
- if (!TransactionIdIsValid(xid))
- break;
-
- SnapBuildProcessChange(builder, xid, buf->origptr);
- ReorderBufferXidSetCatalogChanges(ctx->reorder, xid, buf->origptr);
break;
case XLOG_HEAP_CONFIRM: