From 43baec8366b1d049e1088c0bdc1b7d39cdb7e858 Mon Sep 17 00:00:00 2001
From: "Stephen R. van den Berg" <srb@cuci.nl>
Date: Wed, 4 Mar 2020 15:40:09 +0100
Subject: [PATCH] pgsql: Toggle cache_autoprepared_statements default.

---
 CHANGES                         |  4 ++++
 lib/modules/Sql.pmod/pgsql.pike | 12 ++++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/CHANGES b/CHANGES
index f2033f1972..f9c4b4ed28 100644
--- a/CHANGES
+++ b/CHANGES
@@ -192,6 +192,10 @@ o Sql.pgsql
 
   - Simplify error handling.
 
+  - Toggle cache_autoprepared_statements default to off;
+    turning it on triggers a bug in PostgreSQL sometimes
+    that causes spikes in CPU usage of the database.
+
 o SSL
 
   - When verifying the hostname against the certificate, only accept *
diff --git a/lib/modules/Sql.pmod/pgsql.pike b/lib/modules/Sql.pmod/pgsql.pike
index 35b3334dd4..9c09529772 100644
--- a/lib/modules/Sql.pmod/pgsql.pike
+++ b/lib/modules/Sql.pmod/pgsql.pike
@@ -143,10 +143,12 @@ protected string _sprintf(int type) {
 //!     statement),
 //!     but it can speed up parsing due to increased parallelism.
 //!   @member int "cache_autoprepared_statements"
-//!	If set to zero, it disables the automatic statement prepare and
+//!	If set to one, it enables the automatic statement prepare and
 //!	cache logic; caching prepared statements can be problematic
 //!	when stored procedures and tables are redefined which leave stale
 //!	references in the already cached prepared statements.
+//!     The default is off, because PostgreSQL 10.1 (at least)
+//!     has a bug that makes it spike to 100% CPU sometimes when this is on.
 //!   @member string "client_encoding"
 //!	Character encoding for the client side, it defaults to using
 //!	the default encoding specified by the database, e.g.
@@ -929,7 +931,10 @@ private void startquery(int forcetext, .pgsql_util.sql_result portal, string q,
     if (!sizeof(preparedname) || !tp || !tp.preparedname) {
       if (!sizeof(preparedname))
         preparedname =
-          (portal._unnamedstatementkey = proxy.unnamedstatement->trylock(1))
+          (portal._unnamedstatementkey =
+            (proxy.options.cache_autoprepared_statements
+             ? proxy.unnamedstatement->trylock
+             : proxy.unnamedstatement->lock)(1))
            ? "" : PTSTMTPREFIX + int2hex(ptstmtcount++);
       PD("Parse statement %O=%O\n", preparedname, q);
       plugbuffer = c->start();
@@ -1145,8 +1150,7 @@ private void startquery(int forcetext, .pgsql_util.sql_result portal, string q,
 #endif
         preparedname = tp.preparedname;
       } else if(tp.trun && tp.tparse*FACTORPLAN >= tp.trun
-              && (undefinedp(options.cache_autoprepared_statements)
-             || options.cache_autoprepared_statements))
+              && options.cache_autoprepared_statements)
         preparedname = PREPSTMTPREFIX + int2hex(pstmtcount++);
     } else {
       if (proxy.totalhits >= cachedepth)
-- 
GitLab