From 7a26eeab4c9c35f79ef718df2ffc9bd6968e83b2 Mon Sep 17 00:00:00 2001
From: Amit Kapila <akapila@postgresql.org>
Date: Sat, 19 Sep 2020 10:54:01 +0530
Subject: [PATCH v4 1/2] guc-always-spill.

---
 src/backend/access/transam/xact.c             |  2 ++
 .../replication/logical/reorderbuffer.c       | 19 +++++++++++++++++++
 src/backend/utils/misc/guc.c                  |  9 +++++++++
 src/include/access/xact.h                     |  2 ++
 4 files changed, 32 insertions(+)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index af6afcebb1..5441c0947d 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -80,6 +80,8 @@ bool		XactReadOnly;
 bool		DefaultXactDeferrable = false;
 bool		XactDeferrable;
 
+bool		always_spill_decoding = true;
+
 int			synchronous_commit = SYNCHRONOUS_COMMIT_ON;
 
 /*
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 1975d629a6..1aa0036c9f 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -3044,6 +3044,25 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb)
 {
 	ReorderBufferTXN *txn;
 
+	/* Force spilling if requested */
+	if (always_spill_decoding)
+	{
+		/*
+		 * Pick the largest transaction (or subtransaction) and evict it
+		 * from memory by serializing it to disk.
+		 */
+		txn = ReorderBufferLargestTXN(rb);
+
+		/* we know there has to be one, because the size is not zero */
+		Assert(txn);
+		Assert(txn->size > 0);
+		Assert(rb->size >= txn->size);
+
+		ReorderBufferSerializeTXN(rb, txn);
+
+		return;
+	}
+
 	/* bail out if we haven't exceeded the memory limit */
 	if (rb->size < logical_decoding_work_mem * 1024L)
 		return;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 596bcb7b84..a12e17f4c4 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2036,6 +2036,15 @@ static struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"always_spill_decoding", PGC_USERSET, REPLICATION_PRIMARY,
+			gettext_noop("always spill during logical decoding."),
+		},
+		&always_spill_decoding,
+		true,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index df1b43a932..64da6324ce 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -65,6 +65,8 @@ extern bool xact_is_sampled;
 extern bool DefaultXactDeferrable;
 extern bool XactDeferrable;
 
+extern bool always_spill_decoding;
+
 typedef enum
 {
 	SYNCHRONOUS_COMMIT_OFF,		/* asynchronous commit */
-- 
2.28.0.windows.1

