mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Add idle_in_transaction_session_timeout.
Vik Fearing, reviewed by Stéphane Schildknecht and me, and revised slightly by me.
This commit is contained in:
parent
5871b88487
commit
c6dda1f48e
@ -6063,6 +6063,26 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="guc-idle-in-transaction-session-timeout" xreflabel="idle_in_transaction_session_timeout">
|
||||||
|
<term><varname>idle_in_transaction_session_timeout</varname> (<type>integer</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>idle_in_transaction_session_timeout</> configuration parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Terminate any session with an open transaction that has been idle for
|
||||||
|
longer than the specified duration in milliseconds. This allows any
|
||||||
|
locks held by that session to be released and the connection slot to be reused;
|
||||||
|
it also allows tuples visible only to this transaction to be vacuumed. See
|
||||||
|
<xref linkend="routine-vacuuming"> for more details about this.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The default value of 0 disables this feature.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="guc-vacuum-freeze-table-age" xreflabel="vacuum_freeze_table_age">
|
<varlistentry id="guc-vacuum-freeze-table-age" xreflabel="vacuum_freeze_table_age">
|
||||||
<term><varname>vacuum_freeze_table_age</varname> (<type>integer</type>)
|
<term><varname>vacuum_freeze_table_age</varname> (<type>integer</type>)
|
||||||
<indexterm>
|
<indexterm>
|
||||||
|
@ -725,7 +725,9 @@ ERROR: could not serialize access due to read/write dependencies among transact
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Don't leave connections dangling <quote>idle in transaction</quote>
|
Don't leave connections dangling <quote>idle in transaction</quote>
|
||||||
longer than necessary.
|
longer than necessary. The configuration parameter
|
||||||
|
<xref linkend="guc-idle-in-transaction-session-timeout"> may be used to
|
||||||
|
automatically disconnect lingering sessions.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
int DeadlockTimeout = 1000;
|
int DeadlockTimeout = 1000;
|
||||||
int StatementTimeout = 0;
|
int StatementTimeout = 0;
|
||||||
int LockTimeout = 0;
|
int LockTimeout = 0;
|
||||||
|
int IdleInTransactionSessionTimeout = 0;
|
||||||
bool log_lock_waits = false;
|
bool log_lock_waits = false;
|
||||||
|
|
||||||
/* Pointer to this process's PGPROC and PGXACT structs, if any */
|
/* Pointer to this process's PGPROC and PGXACT structs, if any */
|
||||||
|
@ -2978,6 +2978,18 @@ ProcessInterrupts(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IdleInTransactionSessionTimeoutPending)
|
||||||
|
{
|
||||||
|
/* Has the timeout setting changed since last we looked? */
|
||||||
|
if (IdleInTransactionSessionTimeout > 0)
|
||||||
|
ereport(FATAL,
|
||||||
|
(errcode(ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT),
|
||||||
|
errmsg("terminating connection due to idle-in-transaction timeout")));
|
||||||
|
else
|
||||||
|
IdleInTransactionSessionTimeoutPending = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (ParallelMessagePending)
|
if (ParallelMessagePending)
|
||||||
HandleParallelMessages();
|
HandleParallelMessages();
|
||||||
}
|
}
|
||||||
@ -3553,6 +3565,7 @@ PostgresMain(int argc, char *argv[],
|
|||||||
StringInfoData input_message;
|
StringInfoData input_message;
|
||||||
sigjmp_buf local_sigjmp_buf;
|
sigjmp_buf local_sigjmp_buf;
|
||||||
volatile bool send_ready_for_query = true;
|
volatile bool send_ready_for_query = true;
|
||||||
|
bool disable_idle_in_transaction_timeout = false;
|
||||||
|
|
||||||
/* Initialize startup process environment if necessary. */
|
/* Initialize startup process environment if necessary. */
|
||||||
if (!IsUnderPostmaster)
|
if (!IsUnderPostmaster)
|
||||||
@ -3942,11 +3955,27 @@ PostgresMain(int argc, char *argv[],
|
|||||||
{
|
{
|
||||||
set_ps_display("idle in transaction (aborted)", false);
|
set_ps_display("idle in transaction (aborted)", false);
|
||||||
pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
|
pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
|
||||||
|
|
||||||
|
/* Start the idle-in-transaction timer */
|
||||||
|
if (IdleInTransactionSessionTimeout > 0)
|
||||||
|
{
|
||||||
|
disable_idle_in_transaction_timeout = true;
|
||||||
|
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
|
IdleInTransactionSessionTimeout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (IsTransactionOrTransactionBlock())
|
else if (IsTransactionOrTransactionBlock())
|
||||||
{
|
{
|
||||||
set_ps_display("idle in transaction", false);
|
set_ps_display("idle in transaction", false);
|
||||||
pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
|
pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
|
||||||
|
|
||||||
|
/* Start the idle-in-transaction timer */
|
||||||
|
if (IdleInTransactionSessionTimeout > 0)
|
||||||
|
{
|
||||||
|
disable_idle_in_transaction_timeout = true;
|
||||||
|
enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
|
IdleInTransactionSessionTimeout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3987,7 +4016,16 @@ PostgresMain(int argc, char *argv[],
|
|||||||
DoingCommandRead = false;
|
DoingCommandRead = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (5) check for any other interesting events that happened while we
|
* (5) turn off the idle-in-transaction timeout
|
||||||
|
*/
|
||||||
|
if (disable_idle_in_transaction_timeout)
|
||||||
|
{
|
||||||
|
disable_timeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, false);
|
||||||
|
disable_idle_in_transaction_timeout = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (6) check for any other interesting events that happened while we
|
||||||
* slept.
|
* slept.
|
||||||
*/
|
*/
|
||||||
if (got_SIGHUP)
|
if (got_SIGHUP)
|
||||||
@ -3997,7 +4035,7 @@ PostgresMain(int argc, char *argv[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (6) process the command. But ignore it if we're skipping till
|
* (7) process the command. But ignore it if we're skipping till
|
||||||
* Sync.
|
* Sync.
|
||||||
*/
|
*/
|
||||||
if (ignore_till_sync && firstchar != EOF)
|
if (ignore_till_sync && firstchar != EOF)
|
||||||
|
@ -229,6 +229,7 @@ Section: Class 25 - Invalid Transaction State
|
|||||||
25007 E ERRCODE_SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED schema_and_data_statement_mixing_not_supported
|
25007 E ERRCODE_SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED schema_and_data_statement_mixing_not_supported
|
||||||
25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_sql_transaction
|
25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_sql_transaction
|
||||||
25P02 E ERRCODE_IN_FAILED_SQL_TRANSACTION in_failed_sql_transaction
|
25P02 E ERRCODE_IN_FAILED_SQL_TRANSACTION in_failed_sql_transaction
|
||||||
|
25P03 E ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT idle_in_transaction_session_timeout
|
||||||
|
|
||||||
Section: Class 26 - Invalid SQL Statement Name
|
Section: Class 26 - Invalid SQL Statement Name
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ volatile bool InterruptPending = false;
|
|||||||
volatile bool QueryCancelPending = false;
|
volatile bool QueryCancelPending = false;
|
||||||
volatile bool ProcDiePending = false;
|
volatile bool ProcDiePending = false;
|
||||||
volatile bool ClientConnectionLost = false;
|
volatile bool ClientConnectionLost = false;
|
||||||
|
volatile bool IdleInTransactionSessionTimeoutPending = false;
|
||||||
volatile uint32 InterruptHoldoffCount = 0;
|
volatile uint32 InterruptHoldoffCount = 0;
|
||||||
volatile uint32 QueryCancelHoldoffCount = 0;
|
volatile uint32 QueryCancelHoldoffCount = 0;
|
||||||
volatile uint32 CritSectionCount = 0;
|
volatile uint32 CritSectionCount = 0;
|
||||||
|
@ -70,6 +70,7 @@ static void InitCommunication(void);
|
|||||||
static void ShutdownPostgres(int code, Datum arg);
|
static void ShutdownPostgres(int code, Datum arg);
|
||||||
static void StatementTimeoutHandler(void);
|
static void StatementTimeoutHandler(void);
|
||||||
static void LockTimeoutHandler(void);
|
static void LockTimeoutHandler(void);
|
||||||
|
static void IdleInTransactionSessionTimeoutHandler(void);
|
||||||
static bool ThereIsAtLeastOneRole(void);
|
static bool ThereIsAtLeastOneRole(void);
|
||||||
static void process_startup_options(Port *port, bool am_superuser);
|
static void process_startup_options(Port *port, bool am_superuser);
|
||||||
static void process_settings(Oid databaseid, Oid roleid);
|
static void process_settings(Oid databaseid, Oid roleid);
|
||||||
@ -597,6 +598,8 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
|||||||
RegisterTimeout(DEADLOCK_TIMEOUT, CheckDeadLockAlert);
|
RegisterTimeout(DEADLOCK_TIMEOUT, CheckDeadLockAlert);
|
||||||
RegisterTimeout(STATEMENT_TIMEOUT, StatementTimeoutHandler);
|
RegisterTimeout(STATEMENT_TIMEOUT, StatementTimeoutHandler);
|
||||||
RegisterTimeout(LOCK_TIMEOUT, LockTimeoutHandler);
|
RegisterTimeout(LOCK_TIMEOUT, LockTimeoutHandler);
|
||||||
|
RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
|
IdleInTransactionSessionTimeoutHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1178,6 +1181,13 @@ LockTimeoutHandler(void)
|
|||||||
kill(MyProcPid, SIGINT);
|
kill(MyProcPid, SIGINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
IdleInTransactionSessionTimeoutHandler(void)
|
||||||
|
{
|
||||||
|
IdleInTransactionSessionTimeoutPending = true;
|
||||||
|
InterruptPending = true;
|
||||||
|
SetLatch(MyLatch);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if at least one role is defined in this database cluster.
|
* Returns true if at least one role is defined in this database cluster.
|
||||||
|
@ -2065,6 +2065,17 @@ static struct config_int ConfigureNamesInt[] =
|
|||||||
NULL, NULL, NULL
|
NULL, NULL, NULL
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{"idle_in_transaction_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
||||||
|
gettext_noop("Sets the maximum allowed duration of any idling transaction."),
|
||||||
|
gettext_noop("A value of 0 turns off the timeout."),
|
||||||
|
GUC_UNIT_MS
|
||||||
|
},
|
||||||
|
&IdleInTransactionSessionTimeout,
|
||||||
|
0, 0, INT_MAX,
|
||||||
|
NULL, NULL, NULL
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
||||||
gettext_noop("Minimum age at which VACUUM should freeze a table row."),
|
gettext_noop("Minimum age at which VACUUM should freeze a table row."),
|
||||||
|
@ -529,6 +529,7 @@
|
|||||||
#session_replication_role = 'origin'
|
#session_replication_role = 'origin'
|
||||||
#statement_timeout = 0 # in milliseconds, 0 is disabled
|
#statement_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
#lock_timeout = 0 # in milliseconds, 0 is disabled
|
#lock_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
|
#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled
|
||||||
#vacuum_freeze_min_age = 50000000
|
#vacuum_freeze_min_age = 50000000
|
||||||
#vacuum_freeze_table_age = 150000000
|
#vacuum_freeze_table_age = 150000000
|
||||||
#vacuum_multixact_freeze_min_age = 5000000
|
#vacuum_multixact_freeze_min_age = 5000000
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
extern PGDLLIMPORT volatile bool InterruptPending;
|
extern PGDLLIMPORT volatile bool InterruptPending;
|
||||||
extern PGDLLIMPORT volatile bool QueryCancelPending;
|
extern PGDLLIMPORT volatile bool QueryCancelPending;
|
||||||
extern PGDLLIMPORT volatile bool ProcDiePending;
|
extern PGDLLIMPORT volatile bool ProcDiePending;
|
||||||
|
extern PGDLLIMPORT volatile bool IdleInTransactionSessionTimeoutPending;
|
||||||
|
|
||||||
extern volatile bool ClientConnectionLost;
|
extern volatile bool ClientConnectionLost;
|
||||||
|
|
||||||
|
@ -257,6 +257,7 @@ extern PGPROC *PreparedXactProcs;
|
|||||||
extern int DeadlockTimeout;
|
extern int DeadlockTimeout;
|
||||||
extern int StatementTimeout;
|
extern int StatementTimeout;
|
||||||
extern int LockTimeout;
|
extern int LockTimeout;
|
||||||
|
extern int IdleInTransactionSessionTimeout;
|
||||||
extern bool log_lock_waits;
|
extern bool log_lock_waits;
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ typedef enum TimeoutId
|
|||||||
STANDBY_DEADLOCK_TIMEOUT,
|
STANDBY_DEADLOCK_TIMEOUT,
|
||||||
STANDBY_TIMEOUT,
|
STANDBY_TIMEOUT,
|
||||||
STANDBY_LOCK_TIMEOUT,
|
STANDBY_LOCK_TIMEOUT,
|
||||||
|
IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
|
||||||
/* First user-definable timeout reason */
|
/* First user-definable timeout reason */
|
||||||
USER_TIMEOUT,
|
USER_TIMEOUT,
|
||||||
/* Maximum number of timeout reasons */
|
/* Maximum number of timeout reasons */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user