v20231128-0007-WIP-add-is_transactional-attribute-in-xl_s.patch

text/x-patch

Filename: v20231128-0007-WIP-add-is_transactional-attribute-in-xl_s.patch
Type: text/x-patch
Part: 6
Message: Re: logical decoding and replication of sequences, take 2

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 v20231128-0007
Subject: (WIP) add is_transactional attribute in xl_seq_rec
File+
src/backend/commands/sequence.c 12 0
src/backend/replication/logical/decode.c 4 71
src/backend/replication/logical/reorderbuffer.c 0 401
src/include/access/rmgrlist.h 1 1
src/include/access/xlog_internal.h 1 1
src/include/commands/sequence.h 1 0
src/include/replication/decode.h 0 1
src/include/replication/reorderbuffer.h 0 13
From ace8e4fe23089ba941ffee870a593752ef965dbd Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Mon, 27 Nov 2023 10:15:01 +0000
Subject: [PATCH v20231128 7/8] (WIP) add is_transactional attribute in
 xl_seq_rec

---
 src/backend/commands/sequence.c               |  12 +
 src/backend/replication/logical/decode.c      |  75 +---
 .../replication/logical/reorderbuffer.c       | 401 ------------------
 src/include/access/rmgrlist.h                 |   2 +-
 src/include/access/xlog_internal.h            |   2 +-
 src/include/commands/sequence.h               |   1 +
 src/include/replication/decode.h              |   1 -
 src/include/replication/reorderbuffer.h       |  13 -
 8 files changed, 19 insertions(+), 488 deletions(-)

diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index d8404a6f75e..9da9c8270d9 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -112,6 +112,7 @@ static void init_params(ParseState *pstate, List *options, bool for_identity,
 						List **owned_by);
 static void do_setval(Oid relid, int64 next, bool iscalled);
 static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity);
+static inline bool is_sequence_transactional(Relation seqrel);
 
 
 /*
@@ -255,6 +256,13 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
 	return address;
 }
 
+static inline bool
+is_sequence_transactional(Relation seqrel)
+{
+	return (seqrel->rd_newRelfilelocatorSubid != InvalidSubTransactionId) ||
+		   (seqrel->rd_createSubid != InvalidSubTransactionId);
+}
+
 /*
  * Reset a sequence to its initial value.
  *
@@ -601,6 +609,7 @@ fill_seq_fork_with_data(Relation rel, HeapTuple tuple, ForkNumber forkNum)
 		XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
 
 		xlrec.locator = rel->rd_locator;
+		xlrec.is_transactional = is_sequence_transactional(rel);
 
 		XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
 		XLogRegisterData((char *) tuple->t_data, tuple->t_len);
@@ -1065,6 +1074,7 @@ nextval_internal(Oid relid, bool check_permissions)
 		seq->log_cnt = 0;
 
 		xlrec.locator = seqrel->rd_locator;
+		xlrec.is_transactional = is_sequence_transactional(seqrel);
 
 		XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
 		XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
@@ -1266,6 +1276,8 @@ do_setval(Oid relid, int64 next, bool iscalled)
 		XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
 
 		xlrec.locator = seqrel->rd_locator;
+		xlrec.is_transactional = is_sequence_transactional(seqrel);
+
 		XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
 		XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
 
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index 0248aee83d7..c58b5b45f29 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -1390,6 +1390,7 @@ seq_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 	Snapshot	snapshot = NULL;
 	RepOriginId origin_id = XLogRecGetOrigin(r);
 	bool		transactional;
+	xl_seq_rec *xlrec;
 
 	/* ignore sequences when the plugin does not have the callbacks */
 	if (!ctx->sequences)
@@ -1432,14 +1433,10 @@ seq_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 	/*
 	 * Should we handle the sequence change as transactional or not?
 	 *
-	 * If the relfilenode was created in the current transaction, treat the
-	 * change as transactional and queue it. Otherwise it needs to be treated
-	 * as non-transactional, in which case we just send it to the plugin right
-	 * away.
+	 * XXX: can xlrec be combined with tupledata?
 	 */
-	transactional = ReorderBufferSequenceIsTransactional(ctx->reorder,
-														 target_locator,
-														 xid, NULL);
+	xlrec = (xl_seq_rec *) XLogRecGetData(r);
+	transactional = xlrec->is_transactional;
 
 	/* Skip the change if already processed (per the snapshot). */
 	if (transactional &&
@@ -1486,67 +1483,3 @@ seq_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 							   origin_id, target_locator, transactional,
 							   tuplebuf);
 }
-
-/*
- * Decode relfilenode change
- *
- * Decode SMGR records, so that we can later decide which sequence changes
- * need to be treated as transactional. Most sequence changes are going to
- * be non-transactional (applied as if outside the decoded transaction, not
- * subject to rollback, etc.). Changes for sequences created/altered in the
- * transaction need to be handled as transactional (i.e. applied as part of
- * the decoded transaction, same as all other changes).
- *
- * To decide which of those cases is it we decode XLOG_SMGR_CREATE records
- * and track relfilenodes created in each (sub)transaction. Changes for
- * these relfilenodes are then queued and treated as transactional, while
- * remaining changes are treated as non-transactional.
- *
- * We only care about XLOG_SMGR_CREATE records for "our" database (logical
- * decoding is restricted to a single database), and we do the filtering
- * and skipping, as appropriate.
- */
-void
-smgr_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
-{
-	SnapBuild  *builder = ctx->snapshot_builder;
-	XLogReaderState *r = buf->record;
-	TransactionId xid = XLogRecGetXid(r);
-	uint8		info = XLogRecGetInfo(buf->record) & ~XLR_INFO_MASK;
-	xl_smgr_create *xlrec;
-
-	/*
-	 * Bail out when not decoding sequences, which is currently the only case
-	 * when we need to know about relfilenodes created in a transaction.
-	 */
-	if (!ctx->sequences)
-		return;
-
-	/*
-	 * We only care about XLOG_SMGR_CREATE, because that's what determines if
-	 * the following sequence changes are transactional.
-	 */
-	if (info != XLOG_SMGR_CREATE)
-		return;
-
-	ReorderBufferProcessXid(ctx->reorder, XLogRecGetXid(r), buf->origptr);
-
-	/*
-	 * If we don't have snapshot or we are just fast-forwarding, there is no
-	 * point in decoding relfilenode information.
-	 */
-	if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT ||
-		ctx->fast_forward)
-		return;
-
-	/* only interested in our database */
-	xlrec = (xl_smgr_create *) XLogRecGetData(r);
-	if (xlrec->rlocator.dbOid != ctx->slot->data.database)
-		return;
-
-	/* output plugin doesn't look for this origin, no need to queue */
-	if (FilterByOrigin(ctx, XLogRecGetOrigin(r)))
-		return;
-
-	ReorderBufferAddRelFileLocator(ctx->reorder, xid, buf->endptr, xlrec->rlocator);
-}
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 61781b62bb8..4121269a097 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -268,7 +268,6 @@ static void ReorderBufferTransferSnapToParent(ReorderBufferTXN *txn,
 											  ReorderBufferTXN *subtxn);
 
 static void AssertTXNLsnOrder(ReorderBuffer *rb);
-static void AssertCheckSequences(ReorderBuffer *rb);
 
 /* ---------------------------------------
  * support functions for lsn-order iterating over the ->changes of a
@@ -500,48 +499,12 @@ ReorderBufferReturnTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
 		txn->invalidations = NULL;
 	}
 
-	if (txn->sequences_hash != NULL)
-	{
-		hash_destroy(txn->sequences_hash);
-		txn->sequences_hash = NULL;
-	}
-
 	/* Reset the toast hash */
 	ReorderBufferToastReset(rb, txn);
 
 	pfree(txn);
 }
 
-/*
- * Initialize hash table of relfilenodes created by the transaction.
- *
- * Each entry maps the relfilenode to the (sub)transaction that created the
- * relfilenode - which is also the transaction the sequence change needs to
- * be part of (in transactional case).
- *
- * We don't do this in ReorderBufferGetTXN because that'd allocate the hash
- * for all transactions, and we expect new relfilenodes to be fairly rare.
- * So only do that when adding the first entry.
- */
-static void
-ReorderBufferTXNSequencesInit(ReorderBuffer *rb, ReorderBufferTXN *txn)
-{
-	HASHCTL		hash_ctl;
-
-	/* bail out if already initialized */
-	if (txn->sequences_hash)
-		return;
-
-	/* hash table of sequences, mapping relfilelocator to transaction */
-	hash_ctl.keysize = sizeof(RelFileLocator);
-	hash_ctl.entrysize = sizeof(ReorderBufferSequenceEnt);
-	hash_ctl.hcxt = rb->context;
-
-	/* we expect relfilenodes to be created only rarely, so 32 seems enough */
-	txn->sequences_hash = hash_create("ReorderBufferTXNSequenceHash", 32, &hash_ctl,
-									  HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
-}
-
 /*
  * Get a fresh ReorderBufferChange.
  */
@@ -983,115 +946,6 @@ ReorderBufferQueueMessage(ReorderBuffer *rb, TransactionId xid,
 	}
 }
 
-/*
- * Treat the sequence change as transactional?
- *
- * To decide if a sequence change should be handled as transactional or applied
- * immediately, we need to decide if the relfilenode was created by a running
- * transaction. Each transaction has a hash table of such relfilenodes.
- *
- * A naive approach would be to just loop through all transactions and check
- * each of them, but there may be (easily thousands) of subtransactions, and
- * the check happens for each sequence change. So this could be very costly.
- *
- * To limit the number of transactions we need to check, we transfer the
- * relfilenodes to the top-level xact, which allows us to check just the
- * top-level xacts (and there should be a very limited number of those). We
- * expect relfilenode creation to be a quite rare thing, so this should not
- * waste too much memory. OTOH sequence changes are very common, so making
- * the check cheaper seems like a good trade off.
- *
- * Returns true for transactional changes, false otherwise.
- *
- * Optionaly (when the "xid" parameter is set) returns XID of the (sub)xact
- * to use for queueing transactional changes.
- *
- * XXX As an optimization, maybe we should try searching the current xact (or
- * it's top-level xact) first. If the change is transactional, where we'd
- * find the match.
- */
-bool
-ReorderBufferSequenceIsTransactional(ReorderBuffer *rb,
-									 RelFileLocator rlocator,
-									 TransactionId xidin,
-									 TransactionId *xidout)
-{
-	bool		found = false;
-	ReorderBufferTXN   *txn;
-	ReorderBufferSequenceEnt *entry;
-
-	AssertCheckSequences(rb);
-
-	/*
-	 * Try to lookup transaction with the XID of the change. If it exists, the
-	 * relfilenode would have to be either in it or the top-level transaction
-	 * (if it was created in some earlier subtransaction).
-	 *
-	 * If this is a subxact, we'll search just the top-level hash table. That's
-	 * simpler and likely faster than having to search two hash tables.
-	 */
-	txn = ReorderBufferTXNByXid(rb, xidin, false, NULL, InvalidXLogRecPtr,
-								false);
-
-	if (!txn)
-		return false;
-
-	/* If there's top-level transaction, search that one. */
-	txn = (txn->toptxn) ? txn->toptxn : txn;
-
-	/* transaction has no relfilenodes, can't be transactional */
-	if (!txn->sequences_hash)
-		return false;
-
-	entry = hash_search(txn->sequences_hash,
-						(void *) &rlocator,
-						HASH_FIND,
-						&found);
-
-	if (!found)
-		return false;
-
-	if (xidout)
-		*xidout = entry->txn->xid;
-
-	return true;
-}
-
-/*
- * Cleanup sequences after a subtransaction got aborted.
- *
- * The hash table will get destroyed in ReorderBufferReturnTXN, so we don't
- * need to worry about that. But the entries were copied to the parent xact,
- * and that's still being decoded - we make sure to remove the entries from
- * the aborted one.
- */
-static void
-ReorderBufferSequenceCleanup(ReorderBufferTXN *txn)
-{
-	HASH_SEQ_STATUS scan_status;
-	ReorderBufferSequenceEnt *ent;
-
-	/* Bail out if not a subxact, or if there are no entries. */
-	if (!rbtxn_is_known_subxact(txn))
-		return;
-
-	if (!txn->sequences_hash)
-		return;
-
-	/*
-	 * Scan the top-level transaction hash and remove the entries from it. If
-	 * we have entries for subxact, the top-level hash must have been
-	 * initialized.
-	 */
-	hash_seq_init(&scan_status, txn->sequences_hash);
-	while ((ent = (ReorderBufferSequenceEnt *) hash_seq_search(&scan_status)) != NULL)
-	{
-		(void) hash_search(txn->toptxn->sequences_hash,
-						   (void *) &ent->rlocator,
-						   HASH_REMOVE, NULL);
-	}
-}
-
 /*
  * A transactional sequence change is queued to be processed upon commit
  * and a non-transactional change gets processed immediately.
@@ -1107,8 +961,6 @@ ReorderBufferQueueSequence(ReorderBuffer *rb, TransactionId xid,
 						   RelFileLocator rlocator, bool transactional,
 						   ReorderBufferTupleBuf *tuplebuf)
 {
-	AssertCheckSequences(rb);
-
 	/*
 	 * Change needs to be handled as transactional, because the sequence was
 	 * created in a transaction that is still seen as running. In that case
@@ -1142,9 +994,6 @@ ReorderBufferQueueSequence(ReorderBuffer *rb, TransactionId xid,
 
 		change->data.sequence.tuple = tuplebuf;
 
-		/* lookup the XID for transaction that created the relfilenode */
-		ReorderBufferSequenceIsTransactional(rb, rlocator, xid, &xid);
-
 		/* the XID should be valid for a transactional change */
 		Assert(TransactionIdIsValid(xid));
 
@@ -1167,9 +1016,6 @@ ReorderBufferQueueSequence(ReorderBuffer *rb, TransactionId xid,
 		/* non-transactional changes require a valid snapshot */
 		Assert(snapshot_now);
 
-		/* Make sure the sequence is not in any of the hash tables */
-		Assert(!ReorderBufferSequenceIsTransactional(rb, rlocator, xid, NULL));
-
 		if (xid != InvalidTransactionId)
 			txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
 
@@ -1251,80 +1097,7 @@ ReorderBufferQueueSequence(ReorderBuffer *rb, TransactionId xid,
 	}
 }
 
-/*
- * ReorderBufferAddRelFileLocator
- *		Add newly created relfilenode to the hash table for transaction.
- *
- * If the transaction is already known to be a subtransaction, we add the same
- * entry into the parent transaction (but it still points at the subxact, so
- * that we know where to queue changes or what to discard in case of an abort).
- */
-void
-ReorderBufferAddRelFileLocator(ReorderBuffer *rb, TransactionId xid,
-							   XLogRecPtr lsn, RelFileLocator rlocator)
-{
-	bool		found;
-	ReorderBufferSequenceEnt *entry;
-	ReorderBufferTXN *txn;
-
-	AssertCheckSequences(rb);
-
-	/*
-	 * We only care about sequence relfilenodes for now, and those always have
-	 * a XID. So if there's no XID, don't bother adding them to the hash.
-	 */
-	if (xid == InvalidTransactionId)
-		return;
-
-	/*
-	 * This might be the first change decoded for this transaction, so make
-	 * sure we create it if needed.
-	 */
-	txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
-
-	/*
-	 * First add it to the top-level transaction, but make sure it links to
-	 * the correct subtransaction (so that we add later changes to it).
-	 */
-	if (txn->toptxn)
-	{
-		/* make sure the hash table is initialized */
-		ReorderBufferTXNSequencesInit(rb, txn->toptxn);
 
-		/* search the lookup table */
-		entry = hash_search(txn->toptxn->sequences_hash,
-							(void *) &rlocator,
-							HASH_ENTER,
-							&found);
-
-		/*
-		 * We've just decoded creation of the relfilenode, so if we found it
-		 * in the hash table, something is wrong.
-		 */
-		Assert(!found);
-
-		entry->txn = txn;
-	}
-
-	/* make sure the hash table is initialized */
-	ReorderBufferTXNSequencesInit(rb, txn);
-
-	/* search the lookup table */
-	entry = hash_search(txn->sequences_hash,
-						(void *) &rlocator,
-						HASH_ENTER,
-						&found);
-
-	/*
-	 * We've just decoded creation of the relfilenode, so if we found it in
-	 * the hash table, something is wrong.
-	 */
-	Assert(!found);
-
-	entry->txn = txn;
-
-	AssertCheckSequences(rb);
-}
 
 /*
  * AssertTXNLsnOrder
@@ -1400,161 +1173,6 @@ AssertTXNLsnOrder(ReorderBuffer *rb)
 #endif
 }
 
-/*
- * AssertCheckSequences
- *		Verify consistency of hash tables tracking new relfilenodes.
- *
- * We check that the hash table in the top-level transaction is consistent with
- * respect to the hash tables in it's subxacts. That is, each entry has to be
- * either from the top-level xact or one of it's subtransactions. Likewise, each
- * entry in subxact hash table has to have a match in the top-level hash table.
- */
-static void
-AssertCheckSequences(ReorderBuffer *rb)
-{
-#ifdef USE_ASSERT_CHECKING
-	LogicalDecodingContext *ctx = rb->private_data;
-	dlist_iter	iter;
-
-	/*
-	 * Skip the verification if we don't reach the LSN at which we start
-	 * decoding the contents of transactions yet because until we reach the
-	 * LSN, we could have transactions that don't have the association between
-	 * the top-level transaction and subtransaction yet and consequently have
-	 * the same LSN.  We don't guarantee this association until we try to
-	 * decode the actual contents of transaction. The ordering of the records
-	 * prior to the start_decoding_at LSN should have been checked before the
-	 * restart.
-	 */
-	if (SnapBuildXactNeedsSkip(ctx->snapshot_builder, ctx->reader->EndRecPtr))
-		return;
-
-	/*
-	 * Make sure the relfilenodes from subxacts are properly recorded in the
-	 * top-level transaction hash table.
-	 */
-	dlist_foreach(iter, &rb->toplevel_by_lsn)
-	{
-		int			nentries = 0,
-					nsubentries = 0;
-		dlist_iter	subiter;
-		ReorderBufferTXN *txn = dlist_container(ReorderBufferTXN, node,
-												iter.cur);
-
-		/*
-		 * We don't skip top-level transactions without relfilenodes, because
-		 * there might be a subtransaction with some, and we want to detect
-		 * such cases too.
-		 */
-		if (txn->sequences_hash)
-			nentries = hash_get_num_entries(txn->sequences_hash);
-
-		/* walk all subxacts, and check the hash table in each one */
-		dlist_foreach(subiter, &txn->subtxns)
-		{
-			HASH_SEQ_STATUS scan_status;
-			ReorderBufferSequenceEnt *entry;
-
-			ReorderBufferTXN *subtxn = dlist_container(ReorderBufferTXN, node,
-													   subiter.cur);
-
-			/*
-			 * If this subxact has no relfilenodes, skip it. We'll do the
-			 * check in the opposite direction (that all top-level
-			 * relfilenodes are in the correct subxact) later.
-			 */
-			if (!subtxn->sequences_hash)
-				continue;
-
-			/* add number of relfilenodes in this subxact */
-			nsubentries += hash_get_num_entries(subtxn->sequences_hash);
-
-			/*
-			 * Check that all subxact relfilenodes are in the top-level txn
-			 * too, and are pointing to this subtransaction.
-			 */
-			hash_seq_init(&scan_status, subtxn->sequences_hash);
-			while ((entry = (ReorderBufferSequenceEnt *) hash_seq_search(&scan_status)) != NULL)
-			{
-				bool		found = false;
-				ReorderBufferSequenceEnt *subentry;
-
-				/* search for the same relfilenode in the top-level txn */
-				subentry = hash_search(txn->sequences_hash,
-									   (void *) &entry->rlocator,
-									   HASH_FIND,
-									   &found);
-
-				/*
-				 * The top-level txn hash should have the relfilenode too, and
-				 * it should point to this subxact.
-				 */
-				Assert(found);
-
-				/*
-				 * The entry has to point to the subxact - there's no subxact
-				 * "below" this one to which the relfilenode could belong.
-				 */
-				Assert(subentry->txn == subtxn);
-			}
-		}
-
-		/*
-		 * We shouldn't have more relfilenodes in subtransactions than in the
-		 * top-level one. There might be relfilenodes in the top-level one
-		 * directly, so this needs to be inequality.
-		 */
-		Assert(nentries >= nsubentries);
-
-		/*
-		 * Now do the check in the opposite direction - check that every entry
-		 * in the top-level txn (except those pointing to the top-level txn
-		 * itself) point to one of the subxacts, and there's an entry in the
-		 * subxact hash.
-		 */
-		if (txn->sequences_hash)
-		{
-			HASH_SEQ_STATUS scan_status;
-			ReorderBufferSequenceEnt *entry;
-
-			hash_seq_init(&scan_status, txn->sequences_hash);
-			while ((entry = (ReorderBufferSequenceEnt *) hash_seq_search(&scan_status)) != NULL)
-			{
-				bool		found = false;
-				ReorderBufferSequenceEnt *subentry;
-
-				/* Skip entries for the top-level txn itself. */
-				if (entry->txn == txn)
-					continue;
-
-				/* Is it a subxact of this txn? */
-				Assert(rbtxn_is_known_subxact(entry->txn));
-				Assert(entry->txn->toptxn == txn);
-
-				/*
-				 * Search for the same relfilenode in the subxact (it should
-				 * be initialized, as we expect it to contain the
-				 * relfilenode).
-				 */
-				subentry = hash_search(entry->txn->sequences_hash,
-									   (void *) &entry->rlocator,
-									   HASH_FIND,
-									   &found);
-
-				Assert(found);
-
-				/*
-				 * Check the txn pointer in the top-level hash table entry is
-				 * consistent with the subxact hash table (we already checked
-				 * the subxact entry points to the subxact itself).
-				 */
-				Assert(subentry->txn = entry->txn);
-			}
-		}
-	}
-#endif
-}
-
 /*
  * AssertChangeLsnOrder
  *
@@ -1680,9 +1298,6 @@ ReorderBufferAssignChild(ReorderBuffer *rb, TransactionId xid,
 	subtxn->toplevel_xid = xid;
 	Assert(subtxn->nsubtxns == 0);
 
-	/* There should be no sequence relfilenodes in the subxact yet. */
-	Assert(!subtxn->sequences_hash);
-
 	/* set the reference to top-level transaction */
 	subtxn->toptxn = txn;
 
@@ -3516,9 +3131,6 @@ ReorderBufferFinishPrepared(ReorderBuffer *rb, TransactionId xid,
 	ReorderBufferExecuteInvalidations(txn->ninvalidations,
 									  txn->invalidations);
 
-	/* cleanup: remove sequence relfilenodes from the top-level txn */
-	ReorderBufferSequenceCleanup(txn);
-
 	ReorderBufferCleanupTXN(rb, txn);
 }
 
@@ -3568,13 +3180,8 @@ ReorderBufferAbort(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn,
 	/* cosmetic... */
 	txn->final_lsn = lsn;
 
-	/* remove sequence relfilenodes from the top-level txn */
-	ReorderBufferSequenceCleanup(txn);
-
 	/* remove potential on-disk data, and deallocate */
 	ReorderBufferCleanupTXN(rb, txn);
-
-	AssertCheckSequences(rb);
 }
 
 /*
@@ -3610,13 +3217,8 @@ ReorderBufferAbortOld(ReorderBuffer *rb, TransactionId oldestRunningXid)
 			if (rbtxn_is_streamed(txn))
 				rb->stream_abort(rb, txn, InvalidXLogRecPtr);
 
-			/* remove sequence relfilenodes from the top-level txn */
-			ReorderBufferSequenceCleanup(txn);
-
 			/* remove potential on-disk data, and deallocate this tx */
 			ReorderBufferCleanupTXN(rb, txn);
-
-			AssertCheckSequences(rb);
 		}
 		else
 			return;
@@ -3665,9 +3267,6 @@ ReorderBufferForget(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn)
 	else
 		Assert(txn->ninvalidations == 0);
 
-	/* remove sequence relfilenodes from a top-level txn */
-	ReorderBufferSequenceCleanup(txn);
-
 	/* remove potential on-disk data, and deallocate */
 	ReorderBufferCleanupTXN(rb, txn);
 }
diff --git a/src/include/access/rmgrlist.h b/src/include/access/rmgrlist.h
index 305ca49a55f..c7c60fcbc88 100644
--- a/src/include/access/rmgrlist.h
+++ b/src/include/access/rmgrlist.h
@@ -27,7 +27,7 @@
 /* symbol name, textual name, redo, desc, identify, startup, cleanup, mask, decode */
 PG_RMGR(RM_XLOG_ID, "XLOG", xlog_redo, xlog_desc, xlog_identify, NULL, NULL, NULL, xlog_decode)
 PG_RMGR(RM_XACT_ID, "Transaction", xact_redo, xact_desc, xact_identify, NULL, NULL, NULL, xact_decode)
-PG_RMGR(RM_SMGR_ID, "Storage", smgr_redo, smgr_desc, smgr_identify, NULL, NULL, NULL, smgr_decode)
+PG_RMGR(RM_SMGR_ID, "Storage", smgr_redo, smgr_desc, smgr_identify, NULL, NULL, NULL, NULL)
 PG_RMGR(RM_CLOG_ID, "CLOG", clog_redo, clog_desc, clog_identify, NULL, NULL, NULL, NULL)
 PG_RMGR(RM_DBASE_ID, "Database", dbase_redo, dbase_desc, dbase_identify, NULL, NULL, NULL, NULL)
 PG_RMGR(RM_TBLSPC_ID, "Tablespace", tblspc_redo, tblspc_desc, tblspc_identify, NULL, NULL, NULL, NULL)
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index a6380905fe6..c55974f164b 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -31,7 +31,7 @@
 /*
  * Each page of XLOG file has a header like this:
  */
-#define XLOG_PAGE_MAGIC 0xD114	/* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD115	/* can be used as WAL version indicator */
 
 typedef struct XLogPageHeaderData
 {
diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h
index fe3c813d993..b863f9cda36 100644
--- a/src/include/commands/sequence.h
+++ b/src/include/commands/sequence.h
@@ -48,6 +48,7 @@ typedef FormData_pg_sequence_data *Form_pg_sequence_data;
 typedef struct xl_seq_rec
 {
 	RelFileLocator locator;
+	bool		   is_transactional;
 	/* SEQUENCE TUPLE DATA FOLLOWS AT THE END */
 } xl_seq_rec;
 
diff --git a/src/include/replication/decode.h b/src/include/replication/decode.h
index 8d06247165b..0f8b82c02da 100644
--- a/src/include/replication/decode.h
+++ b/src/include/replication/decode.h
@@ -28,7 +28,6 @@ extern void xact_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void standby_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void logicalmsg_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void seq_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
-extern void smgr_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 
 extern void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx,
 										 XLogReaderState *record);
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index a44a0f4dfb9..a9e41f9a268 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -400,12 +400,6 @@ typedef struct ReorderBufferTXN
 	 */
 	HTAB	   *toast_hash;
 
-	/*
-	 * Sequence relfilenodes created in this transaction (also includes
-	 * altered sequences, which assigns new relfilenode).
-	 */
-	HTAB	   *sequences_hash;
-
 	/*
 	 * non-hierarchical list of subtransactions that are *not* aborted. Only
 	 * used in toplevel transactions.
@@ -786,11 +780,4 @@ extern void ReorderBufferSetRestartPoint(ReorderBuffer *rb, XLogRecPtr ptr);
 
 extern void StartupReorderBuffer(void);
 
-extern void ReorderBufferAddRelFileLocator(ReorderBuffer *rb, TransactionId xid,
-										   XLogRecPtr lsn, RelFileLocator rlocator);
-extern bool ReorderBufferSequenceIsTransactional(ReorderBuffer *rb,
-												 RelFileLocator locator,
-												 TransactionId xidin,
-												 TransactionId *xidout);
-
 #endif
-- 
2.41.0