v6-0001-GetNewOidWithIndex_log_output.patch

application/octet-stream

Filename: v6-0001-GetNewOidWithIndex_log_output.patch
Type: application/octet-stream
Part: 0
Message: Re: BUG #16722: PG hanging on COPY when table has close to 2^32 toasts in the table.

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 v6-0001
Subject: GetNewOidWithIndex_log_output
File+
src/backend/catalog/catalog.c 49 0
From a1e2ec7044feadd3209678b8c153dfd069ec2037 Mon Sep 17 00:00:00 2001
From: Tomohiro <hiramit.tm@gmail.com>
Date: Mon, 22 Mar 2021 14:24:39 +0900
Subject: [PATCH v6] GetNewOidWithIndex_log_output

---
 src/backend/catalog/catalog.c | 49 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index e2ed80a..4afa979 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -48,6 +48,13 @@
 #include "utils/syscache.h"
 
 /*
+ * Parameters to determine when to emit a warning in
+ * GetNewOidWithIndex()
+ */
+#define GETNEWOID_WARN_THRESHOLD 1000000
+#define GETNEWOID_WARN_MAX_INTERVAL 128000000
+
+/*
  * IsSystemRelation
  *		True iff the relation is either a system catalog or a toast table.
  *		See IsCatalogRelation for the exact definition of a system catalog.
@@ -318,6 +325,8 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
 	SysScanDesc scan;
 	ScanKeyData key;
 	bool		collides;
+	uint64		retries = 0;
+	uint64		retries_before_warn = GETNEWOID_WARN_THRESHOLD;
 
 	/* Only system relations are supported */
 	Assert(IsSystemRelation(relation));
@@ -353,8 +362,48 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
 		collides = HeapTupleIsValid(systable_getnext(scan));
 
 		systable_endscan(scan);
+
+		/*
+		 * Warn users that we iterate more than GETNEWOID_WARN_THRESHOLD but
+		 * have not yet found OID unused in the relation. Then repeat warning
+		 * with exponentially increasing intervals until we iterate more than
+		 * GETNEWOID_WARN_MAX_INTERVAL. Finally repeat warning every
+		 * GETNEWOID_WARN_MAX_INTERVAL unless an unused OID is found. This
+		 * logic is necessary not to fill up the server log with the similar
+		 * messages.
+		 */
+		if (retries >= retries_before_warn)
+		{
+			ereport(WARNING,
+					(errmsg("still finding an unused OID within relation \"%s\"",
+							RelationGetRelationName(relation)),
+					 errdetail("OID candidates were checked \"%llu\"  times, but no unused OID is yet found.",
+							   (unsigned long long) retries)));
+
+			/*
+			 * Double the number of retries to do before warning next until it
+			 * reaches GETNEWOID_WARN_MAX_INTERVAL.
+			 */
+			if (retries_before_warn * 2 <= GETNEWOID_WARN_MAX_INTERVAL)
+				retries_before_warn *= 2;
+			else
+				retries_before_warn += GETNEWOID_WARN_MAX_INTERVAL;
+		}
+
+		retries++;
 	} while (collides);
 
+	/*
+	 * If at least one warning is emitted, also warn the completion of OID
+	 * assignment.
+	 */
+	if (retries > GETNEWOID_WARN_THRESHOLD)
+	{
+		ereport(WARNING,
+				(errmsg("new OID has been assigned in relation \"%s\" after \"%llu\" retries",
+						RelationGetRelationName(relation), (unsigned long long) retries)));
+	}
+
 	return newOid;
 }
 
-- 
1.8.3.1