Skip to content

Commit c6dda1f

Browse files
committed
Add idle_in_transaction_session_timeout.
Vik Fearing, reviewed by Stéphane Schildknecht and me, and revised slightly by me.
1 parent 5871b88 commit c6dda1f

File tree

12 files changed

+91
-3
lines changed

12 files changed

+91
-3
lines changed

doc/src/sgml/config.sgml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6063,6 +6063,26 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
60636063
</listitem>
60646064
</varlistentry>
60656065

6066+
<varlistentry id="guc-idle-in-transaction-session-timeout" xreflabel="idle_in_transaction_session_timeout">
6067+
<term><varname>idle_in_transaction_session_timeout</varname> (<type>integer</type>)
6068+
<indexterm>
6069+
<primary><varname>idle_in_transaction_session_timeout</> configuration parameter</primary>
6070+
</indexterm>
6071+
</term>
6072+
<listitem>
6073+
<para>
6074+
Terminate any session with an open transaction that has been idle for
6075+
longer than the specified duration in milliseconds. This allows any
6076+
locks held by that session to be released and the connection slot to be reused;
6077+
it also allows tuples visible only to this transaction to be vacuumed. See
6078+
<xref linkend="routine-vacuuming"> for more details about this.
6079+
</para>
6080+
<para>
6081+
The default value of 0 disables this feature.
6082+
</para>
6083+
</listitem>
6084+
</varlistentry>
6085+
60666086
<varlistentry id="guc-vacuum-freeze-table-age" xreflabel="vacuum_freeze_table_age">
60676087
<term><varname>vacuum_freeze_table_age</varname> (<type>integer</type>)
60686088
<indexterm>

doc/src/sgml/mvcc.sgml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,9 @@ ERROR: could not serialize access due to read/write dependencies among transact
725725
<listitem>
726726
<para>
727727
Don't leave connections dangling <quote>idle in transaction</quote>
728-
longer than necessary.
728+
longer than necessary. The configuration parameter
729+
<xref linkend="guc-idle-in-transaction-session-timeout"> may be used to
730+
automatically disconnect lingering sessions.
729731
</para>
730732
</listitem>
731733
<listitem>

src/backend/storage/lmgr/proc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
int DeadlockTimeout = 1000;
5959
int StatementTimeout = 0;
6060
int LockTimeout = 0;
61+
int IdleInTransactionSessionTimeout = 0;
6162
bool log_lock_waits = false;
6263

6364
/* Pointer to this process's PGPROC and PGXACT structs, if any */

src/backend/tcop/postgres.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,6 +2978,18 @@ ProcessInterrupts(void)
29782978
}
29792979
}
29802980

2981+
if (IdleInTransactionSessionTimeoutPending)
2982+
{
2983+
/* Has the timeout setting changed since last we looked? */
2984+
if (IdleInTransactionSessionTimeout > 0)
2985+
ereport(FATAL,
2986+
(errcode(ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT),
2987+
errmsg("terminating connection due to idle-in-transaction timeout")));
2988+
else
2989+
IdleInTransactionSessionTimeoutPending = false;
2990+
2991+
}
2992+
29812993
if (ParallelMessagePending)
29822994
HandleParallelMessages();
29832995
}
@@ -3553,6 +3565,7 @@ PostgresMain(int argc, char *argv[],
35533565
StringInfoData input_message;
35543566
sigjmp_buf local_sigjmp_buf;
35553567
volatile bool send_ready_for_query = true;
3568+
bool disable_idle_in_transaction_timeout = false;
35563569

35573570
/* Initialize startup process environment if necessary. */
35583571
if (!IsUnderPostmaster)
@@ -3942,11 +3955,27 @@ PostgresMain(int argc, char *argv[],
39423955
{
39433956
set_ps_display("idle in transaction (aborted)", false);
39443957
pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
3958+
3959+
/* Start the idle-in-transaction timer */
3960+
if (IdleInTransactionSessionTimeout > 0)
3961+
{
3962+
disable_idle_in_transaction_timeout = true;
3963+
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
3964+
IdleInTransactionSessionTimeout);
3965+
}
39453966
}
39463967
else if (IsTransactionOrTransactionBlock())
39473968
{
39483969
set_ps_display("idle in transaction", false);
39493970
pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
3971+
3972+
/* Start the idle-in-transaction timer */
3973+
if (IdleInTransactionSessionTimeout > 0)
3974+
{
3975+
disable_idle_in_transaction_timeout = true;
3976+
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
3977+
IdleInTransactionSessionTimeout);
3978+
}
39503979
}
39513980
else
39523981
{
@@ -3987,7 +4016,16 @@ PostgresMain(int argc, char *argv[],
39874016
DoingCommandRead = false;
39884017

39894018
/*
3990-
* (5) check for any other interesting events that happened while we
4019+
* (5) turn off the idle-in-transaction timeout
4020+
*/
4021+
if (disable_idle_in_transaction_timeout)
4022+
{
4023+
disable_timeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, false);
4024+
disable_idle_in_transaction_timeout = false;
4025+
}
4026+
4027+
/*
4028+
* (6) check for any other interesting events that happened while we
39914029
* slept.
39924030
*/
39934031
if (got_SIGHUP)
@@ -3997,7 +4035,7 @@ PostgresMain(int argc, char *argv[],
39974035
}
39984036

39994037
/*
4000-
* (6) process the command. But ignore it if we're skipping till
4038+
* (7) process the command. But ignore it if we're skipping till
40014039
* Sync.
40024040
*/
40034041
if (ignore_till_sync && firstchar != EOF)

src/backend/utils/errcodes.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ Section: Class 25 - Invalid Transaction State
229229
25007 E ERRCODE_SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED schema_and_data_statement_mixing_not_supported
230230
25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_sql_transaction
231231
25P02 E ERRCODE_IN_FAILED_SQL_TRANSACTION in_failed_sql_transaction
232+
25P03 E ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT idle_in_transaction_session_timeout
232233

233234
Section: Class 26 - Invalid SQL Statement Name
234235

src/backend/utils/init/globals.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ volatile bool InterruptPending = false;
3030
volatile bool QueryCancelPending = false;
3131
volatile bool ProcDiePending = false;
3232
volatile bool ClientConnectionLost = false;
33+
volatile bool IdleInTransactionSessionTimeoutPending = false;
3334
volatile uint32 InterruptHoldoffCount = 0;
3435
volatile uint32 QueryCancelHoldoffCount = 0;
3536
volatile uint32 CritSectionCount = 0;

src/backend/utils/init/postinit.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ static void InitCommunication(void);
7070
static void ShutdownPostgres(int code, Datum arg);
7171
static void StatementTimeoutHandler(void);
7272
static void LockTimeoutHandler(void);
73+
static void IdleInTransactionSessionTimeoutHandler(void);
7374
static bool ThereIsAtLeastOneRole(void);
7475
static void process_startup_options(Port *port, bool am_superuser);
7576
static void process_settings(Oid databaseid, Oid roleid);
@@ -597,6 +598,8 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
597598
RegisterTimeout(DEADLOCK_TIMEOUT, CheckDeadLockAlert);
598599
RegisterTimeout(STATEMENT_TIMEOUT, StatementTimeoutHandler);
599600
RegisterTimeout(LOCK_TIMEOUT, LockTimeoutHandler);
601+
RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
602+
IdleInTransactionSessionTimeoutHandler);
600603
}
601604

602605
/*
@@ -1178,6 +1181,13 @@ LockTimeoutHandler(void)
11781181
kill(MyProcPid, SIGINT);
11791182
}
11801183

1184+
static void
1185+
IdleInTransactionSessionTimeoutHandler(void)
1186+
{
1187+
IdleInTransactionSessionTimeoutPending = true;
1188+
InterruptPending = true;
1189+
SetLatch(MyLatch);
1190+
}
11811191

11821192
/*
11831193
* Returns true if at least one role is defined in this database cluster.

src/backend/utils/misc/guc.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,17 @@ static struct config_int ConfigureNamesInt[] =
20652065
NULL, NULL, NULL
20662066
},
20672067

2068+
{
2069+
{"idle_in_transaction_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
2070+
gettext_noop("Sets the maximum allowed duration of any idling transaction."),
2071+
gettext_noop("A value of 0 turns off the timeout."),
2072+
GUC_UNIT_MS
2073+
},
2074+
&IdleInTransactionSessionTimeout,
2075+
0, 0, INT_MAX,
2076+
NULL, NULL, NULL
2077+
},
2078+
20682079
{
20692080
{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
20702081
gettext_noop("Minimum age at which VACUUM should freeze a table row."),

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@
529529
#session_replication_role = 'origin'
530530
#statement_timeout = 0 # in milliseconds, 0 is disabled
531531
#lock_timeout = 0 # in milliseconds, 0 is disabled
532+
#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled
532533
#vacuum_freeze_min_age = 50000000
533534
#vacuum_freeze_table_age = 150000000
534535
#vacuum_multixact_freeze_min_age = 5000000

src/include/miscadmin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
extern PGDLLIMPORT volatile bool InterruptPending;
8181
extern PGDLLIMPORT volatile bool QueryCancelPending;
8282
extern PGDLLIMPORT volatile bool ProcDiePending;
83+
extern PGDLLIMPORT volatile bool IdleInTransactionSessionTimeoutPending;
8384

8485
extern volatile bool ClientConnectionLost;
8586

src/include/storage/proc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ extern PGPROC *PreparedXactProcs;
257257
extern int DeadlockTimeout;
258258
extern int StatementTimeout;
259259
extern int LockTimeout;
260+
extern int IdleInTransactionSessionTimeout;
260261
extern bool log_lock_waits;
261262

262263

src/include/utils/timeout.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ typedef enum TimeoutId
3030
STANDBY_DEADLOCK_TIMEOUT,
3131
STANDBY_TIMEOUT,
3232
STANDBY_LOCK_TIMEOUT,
33+
IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
3334
/* First user-definable timeout reason */
3435
USER_TIMEOUT,
3536
/* Maximum number of timeout reasons */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy