Deal with "terminating connection due to idle-in-transaction timeout" error.
authorTatsuo Ishii <ishii@sraoss.co.jp>
Thu, 6 Dec 2018 08:20:32 +0000 (17:20 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Thu, 6 Dec 2018 08:24:40 +0000 (17:24 +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 e4e1997ced5fe504756e5a4a2591b7a47000a0fb..668aee53a7a24236927112090126c517bc0b068a 100644 (file)
@@ -168,6 +168,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 208c94547e99d1682f2e525e7bd4fed9a4e3dad2..a2fe152eaefbd20e6184578d3f185c6bc51aa06f 100644 (file)
@@ -66,6 +66,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);
@@ -4457,6 +4458,19 @@ static int detect_error(POOL_CONNECTION *backend, char *error_code, int major, c
        return is_error;
 }
 
+
+int
+detect_idle_in_transaction_sesion_timeout_error(POOL_CONNECTION * backend, int major)
+{
+       int                     r = detect_error(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;
+}
+
 /*
  * The function forwards the NOTICE mesaage received from one backend
  * to the frontend and also puts the human readable message to the
@@ -4890,6 +4904,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
                                 */