Deal with "terminating connection due to idle-in-transaction timeout" error.
authorTatsuo Ishii <ishii@sraoss.co.jp>
Thu, 6 Dec 2018 06:35:06 +0000 (15:35 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Thu, 6 Dec 2018 06:35:06 +0000 (15:35 +0900)
If idle_in_transaction_session_timeout parameter is set to reasonably
short in postgresql.conf, the fatal error easily occurs and the
connection from Pgpool-II to backend is terminated. This leads to
Pgpool-II either hang (if only one of PostgreSQL equips equips the
parameter) or unwanted failover (if all PostgreSQL equips with the
parameter), and both are not good. So intercept the message and send
the same message to frontend then exit to terminate the connection to
frontend. This is similar treatment as the error "connection was
terminated due to conflict with recovery, User was holding a relation
lock for too long."

Per bug 448.

src/include/protocol/pool_proto_modules.h
src/protocol/pool_process_query.c

index d8bd3a64ce545f6d256edfc9ec9a1465981a17c8..a4ab34d94b89f038b2e893e34d82d32fddd4050a 100644 (file)
@@ -167,6 +167,7 @@ extern int  detect_deadlock_error(POOL_CONNECTION * master, int major);
 extern int     detect_serialization_error(POOL_CONNECTION * master, int major, bool unread);
 extern int     detect_active_sql_transaction_error(POOL_CONNECTION * backend, int major);
 extern int     detect_query_cancel_error(POOL_CONNECTION * backend, int major);
+extern int     detect_idle_in_transaction_sesion_timeout_error(POOL_CONNECTION * backend, int major);
 extern bool is_partition_table(POOL_CONNECTION_POOL * backend, Node *node);
 extern POOL_STATUS pool_discard_packet(POOL_CONNECTION_POOL * cp);
 extern void query_cache_register(char kind, POOL_CONNECTION * frontend, char *database, char *data, int data_len);
index cb951bca8e6df3ed4a31b63ed9e0bb7c52f87e0c..22dd54795c25c2b56112a16cb3a824893c9d79f0 100644 (file)
@@ -70,6 +70,7 @@
 #define QUERY_CANCEL_ERROR_CODE "57014"
 #define ADMIN_SHUTDOWN_ERROR_CODE "57P01"
 #define CRASH_SHUTDOWN_ERROR_CODE "57P02"
+#define IDLE_IN_TRANSACTION_SESSION_TIMEOUT_ERROR_CODE "25P03"
 
 static int     reset_backend(POOL_CONNECTION_POOL * backend, int qcnt);
 static char *get_insert_command_table_name(InsertStmt *node);
@@ -4286,6 +4287,19 @@ detect_query_cancel_error(POOL_CONNECTION * backend, int major)
        return r;
 }
 
+
+int
+detect_idle_in_transaction_sesion_timeout_error(POOL_CONNECTION * backend, int major)
+{
+       int                     r = extract_message(backend, IDLE_IN_TRANSACTION_SESSION_TIMEOUT_ERROR_CODE, major, 'E', true);
+
+       if (r == SPECIFIED_ERROR)
+               ereport(DEBUG1,
+                               (errmsg("detecting idle in transaction session timeout error"),
+                                errdetail("idle in transaction session timeout error message from backend")));
+       return r;
+}
+
 /*
  * extract_message: extract specified error by an error code.
  * returns 0 in case of sucess or 1 in case of specified error.
@@ -4822,6 +4836,17 @@ SELECT_RETRY:
 
                                }
 
+                               /*
+                                * connection was terminated due to idle_in_transaction_sesion_timeout expired
+                                */
+                               r = detect_idle_in_transaction_sesion_timeout_error(CONNECTION(backend, i), MAJOR(backend));
+                               if (r == SPECIFIED_ERROR)
+                               {
+                                       ereport(FATAL,
+                                                       (pool_error_code(IDLE_IN_TRANSACTION_SESSION_TIMEOUT_ERROR_CODE),
+                                                        errmsg("terminating connection due to idle-in-transaction timeout")));
+                               }
+
                                /*
                                 * admin shutdown postmaster or postmaster goes down
                                 */