a On Sat, 23 Dec 2023 at 10:40, Japin Li <japi...@hotmail.com> wrote: > On Sat, 23 Dec 2023 at 08:32, Japin Li <japi...@hotmail.com> wrote: >> On Fri, 22 Dec 2023 at 23:30, Junwang Zhao <zhjw...@gmail.com> wrote: >>> On Fri, Dec 22, 2023 at 10:44 PM Japin Li <japi...@hotmail.com> wrote: >>>> >>>> >>>> On Fri, 22 Dec 2023 at 22:37, Junwang Zhao <zhjw...@gmail.com> wrote: >>>> > On Fri, Dec 22, 2023 at 10:25 PM Japin Li <japi...@hotmail.com> wrote: >>>> >> I try to set idle_in_transaction_session_timeout after begin >>>> >> transaction, >>>> >> it changes immediately, so I think transaction_timeout should also be >>>> >> take >>>> >> immediately. >>>> > >>>> > Ah, right, idle_in_transaction_session_timeout is set after the set >>>> > command finishes and before the backend send *ready for query* >>>> > to the client, so the value of the GUC is already set before >>>> > next command. >>>> > >>>> >>>> I mean, is it possible to set transaction_timeout before next comand? >>>> >>> Yeah, it's possible, set transaction_timeout in the when it first >>> goes into *idle in transaction* mode, see the attached files. >>> >> >> Thanks for updating the patch, LGTM. > > Sorry for the noise! > > Read the previous threads, I find why the author enable transaction_timeout > in start_xact_command(). > > The v15 patch cannot handle COMMIT AND CHAIN, see [1]. For example: > > SET transaction_timeout TO '2s'; BEGIN; SELECT 1, pg_sleep(1); COMMIT AND > CHAIN; SELECT 2, pg_sleep(1); COMMIT; > > The transaction_timeout do not reset when executing COMMIT AND CHAIN. > > [1] > https://www.postgresql.org/message-id/a906dea1-76a1-4f26-76c5-a7efad3ef5b8%40oss.nttdata.com
Attach v16 to solve this. Any suggestions? -- Regrads, Japin Li ChengDu WenWu Information Technology Co., Ltd.
>From a9d79c5a013da8fa707556f87a34ff3ade779729 Mon Sep 17 00:00:00 2001 From: "Andrey M. Borodin" <x4mmm@night.local> Date: Sun, 3 Dec 2023 23:18:00 +0500 Subject: [PATCH v16 1/2] Introduce transaction_timeout This commit adds timeout that is expected to be used as a prevention of long-running queries. Any session within transaction will be terminated after spanning longer than this timeout. However, this timeout is not applied to prepared transactions. Only transactions with user connections are affected. Author: Andrey Borodin <amboro...@acm.org> Reviewed-by: Nikolay Samokhvalov <samokhva...@gmail.com> Reviewed-by: Andres Freund <and...@anarazel.de> Reviewed-by: Fujii Masao <masao.fu...@oss.nttdata.com> Reviewed-by: bt23nguyent <bt23nguy...@oss.nttdata.com> Reviewed-by: Yuhang Qiu <iam...@gmail.com> Reviewed-by: Japin Li <japi...@hotmail.com> Discussion: https://postgr.es/m/CAAhFRxiQsRs2Eq5kCo9nXE3HTugsAAJdSQSmxncivebAxdmBjQ%40mail.gmail.com --- doc/src/sgml/config.sgml | 35 +++++++++++ src/backend/postmaster/autovacuum.c | 2 + src/backend/storage/lmgr/proc.c | 1 + src/backend/tcop/postgres.c | 27 +++++++- src/backend/utils/errcodes.txt | 1 + src/backend/utils/init/globals.c | 1 + src/backend/utils/init/postinit.c | 10 +++ src/backend/utils/misc/guc_tables.c | 11 ++++ src/backend/utils/misc/postgresql.conf.sample | 1 + src/bin/pg_dump/pg_backup_archiver.c | 2 + src/bin/pg_dump/pg_dump.c | 2 + src/bin/pg_rewind/libpq_source.c | 1 + src/include/miscadmin.h | 1 + src/include/storage/proc.h | 1 + src/include/utils/timeout.h | 1 + src/test/isolation/Makefile | 5 +- src/test/isolation/expected/timeouts.out | 63 ++++++++++++++++++- src/test/isolation/specs/timeouts.spec | 30 +++++++++ 18 files changed, 190 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index b5624ca884..d62edcf83b 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -9134,6 +9134,41 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; </listitem> </varlistentry> + <varlistentry id="guc-transaction-timeout" xreflabel="transaction_timeout"> + <term><varname>transaction_timeout</varname> (<type>integer</type>) + <indexterm> + <primary><varname>transaction_timeout</varname> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + Terminate any session that spans longer than the specified amount of + time in transaction. The limit applies both to explicit transactions + (started with <command>BEGIN</command>) and to implicitly started + transaction corresponding to single statement. But this limit is not + applied to prepared transactions. + If this value is specified without units, it is taken as milliseconds. + A value of zero (the default) disables the timeout. + </para> + + <para> + If <varname>transaction_timeout</varname> is shorter than + <varname>idle_in_transaction_session_timeout</varname> or <varname>statement_timeout</varname> + <varname>transaction_timeout</varname> will invalidate longer timeout. + </para> + + <para> + Setting <varname>transaction_timeout</varname> in + <filename>postgresql.conf</filename> is not recommended because it would + affect all sessions. + </para> + + <para> + Prepared transactions are not subject for this timeout. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-lock-timeout" xreflabel="lock_timeout"> <term><varname>lock_timeout</varname> (<type>integer</type>) <indexterm> diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index b04fcfc8c8..e6fa1cfdc2 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -586,6 +586,7 @@ AutoVacLauncherMain(int argc, char *argv[]) * regular maintenance from being executed. */ SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); + SetConfigOption("transaction_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); SetConfigOption("idle_in_transaction_session_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); @@ -1591,6 +1592,7 @@ AutoVacWorkerMain(int argc, char *argv[]) * regular maintenance from being executed. */ SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); + SetConfigOption("transaction_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); SetConfigOption("lock_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); SetConfigOption("idle_in_transaction_session_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index b6451d9d08..4be06c1e5d 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -59,6 +59,7 @@ int DeadlockTimeout = 1000; int StatementTimeout = 0; int LockTimeout = 0; int IdleInTransactionSessionTimeout = 0; +int TransactionTimeout = 0; int IdleSessionTimeout = 0; bool log_lock_waits = false; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 7298a187d1..a2611cf8e6 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -2745,6 +2745,10 @@ start_xact_command(void) { StartTransactionCommand(); + /* Schedule or reschedule transaction timeout */ + if (TransactionTimeout > 0) + enable_timeout_after(TRANSACTION_TIMEOUT, TransactionTimeout); + xact_started = true; } @@ -3426,6 +3430,17 @@ ProcessInterrupts(void) IdleInTransactionSessionTimeoutPending = false; } + if (TransactionTimeoutPending) + { + /* As above, ignore the signal if the GUC has been reset to zero. */ + if (TransactionTimeout > 0) + ereport(FATAL, + (errcode(ERRCODE_TRANSACTION_TIMEOUT), + errmsg("terminating connection due to transaction timeout"))); + else + TransactionTimeoutPending = false; + } + if (IdleSessionTimeoutPending) { /* As above, ignore the signal if the GUC has been reset to zero. */ @@ -4491,7 +4506,8 @@ PostgresMain(const char *dbname, const char *username) pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL); /* Start the idle-in-transaction timer */ - if (IdleInTransactionSessionTimeout > 0) + if (IdleInTransactionSessionTimeout > 0 + && (IdleInTransactionSessionTimeout < TransactionTimeout || TransactionTimeout == 0)) { idle_in_transaction_timeout_enabled = true; enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, @@ -4504,7 +4520,8 @@ PostgresMain(const char *dbname, const char *username) pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL); /* Start the idle-in-transaction timer */ - if (IdleInTransactionSessionTimeout > 0) + if (IdleInTransactionSessionTimeout > 0 + && (IdleInTransactionSessionTimeout < TransactionTimeout || TransactionTimeout == 0)) { idle_in_transaction_timeout_enabled = true; enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, @@ -4562,6 +4579,9 @@ PostgresMain(const char *dbname, const char *username) enable_timeout_after(IDLE_SESSION_TIMEOUT, IdleSessionTimeout); } + + if (get_timeout_active(TRANSACTION_TIMEOUT)) + disable_timeout(TRANSACTION_TIMEOUT, false); } /* Report any recently-changed GUC options */ @@ -5120,7 +5140,8 @@ enable_statement_timeout(void) /* must be within an xact */ Assert(xact_started); - if (StatementTimeout > 0) + if (StatementTimeout > 0 + && (StatementTimeout < TransactionTimeout || TransactionTimeout == 0)) { if (!get_timeout_active(STATEMENT_TIMEOUT)) enable_timeout_after(STATEMENT_TIMEOUT, StatementTimeout); diff --git a/src/backend/utils/errcodes.txt b/src/backend/utils/errcodes.txt index 8e97a0150f..8f1157afee 100644 --- a/src/backend/utils/errcodes.txt +++ b/src/backend/utils/errcodes.txt @@ -252,6 +252,7 @@ Section: Class 25 - Invalid Transaction State 25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_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 +25P04 E ERRCODE_TRANSACTION_TIMEOUT transaction_timeout Section: Class 26 - Invalid SQL Statement Name diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 60bc1217fb..fd586c193c 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -33,6 +33,7 @@ volatile sig_atomic_t ProcDiePending = false; volatile sig_atomic_t CheckClientConnectionPending = false; volatile sig_atomic_t ClientConnectionLost = false; volatile sig_atomic_t IdleInTransactionSessionTimeoutPending = false; +volatile sig_atomic_t TransactionTimeoutPending = false; volatile sig_atomic_t IdleSessionTimeoutPending = false; volatile sig_atomic_t ProcSignalBarrierPending = false; volatile sig_atomic_t LogMemoryContextPending = false; diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 552cf9d950..64be4de0c7 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -75,6 +75,7 @@ static void ShutdownPostgres(int code, Datum arg); static void StatementTimeoutHandler(void); static void LockTimeoutHandler(void); static void IdleInTransactionSessionTimeoutHandler(void); +static void TransactionTimeoutHandler(void); static void IdleSessionTimeoutHandler(void); static void IdleStatsUpdateTimeoutHandler(void); static void ClientCheckTimeoutHandler(void); @@ -764,6 +765,7 @@ InitPostgres(const char *in_dbname, Oid dboid, RegisterTimeout(LOCK_TIMEOUT, LockTimeoutHandler); RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, IdleInTransactionSessionTimeoutHandler); + RegisterTimeout(TRANSACTION_TIMEOUT, TransactionTimeoutHandler); RegisterTimeout(IDLE_SESSION_TIMEOUT, IdleSessionTimeoutHandler); RegisterTimeout(CLIENT_CONNECTION_CHECK_TIMEOUT, ClientCheckTimeoutHandler); RegisterTimeout(IDLE_STATS_UPDATE_TIMEOUT, @@ -1395,6 +1397,14 @@ LockTimeoutHandler(void) kill(MyProcPid, SIGINT); } +static void +TransactionTimeoutHandler(void) +{ + TransactionTimeoutPending = true; + InterruptPending = true; + SetLatch(MyLatch); +} + static void IdleInTransactionSessionTimeoutHandler(void) { diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 9f59440526..c5cfbef02b 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -2556,6 +2556,17 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"transaction_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, + gettext_noop("Sets the maximum allowed time in a transaction with session (not a prepared transaction)."), + gettext_noop("A value of 0 turns off the timeout."), + GUC_UNIT_MS + }, + &TransactionTimeout, + 0, 0, INT_MAX, + NULL, NULL, NULL + }, + { {"idle_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed idle time between queries, when not in a transaction."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index b2809c711a..0b37117eb7 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -700,6 +700,7 @@ #default_transaction_deferrable = off #session_replication_role = 'origin' #statement_timeout = 0 # in milliseconds, 0 is disabled +#transaction_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 #idle_session_timeout = 0 # in milliseconds, 0 is disabled diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 256d1e35a4..3342971bd0 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -3115,6 +3115,8 @@ _doSetFixedOutputState(ArchiveHandle *AH) ahprintf(AH, "SET statement_timeout = 0;\n"); ahprintf(AH, "SET lock_timeout = 0;\n"); ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n"); + // TODO: AB: do we need spacial handling for this? + ahprintf(AH, "SET transaction_timeout = 0;\n"); /* Select the correct character set encoding */ ahprintf(AH, "SET client_encoding = '%s';\n", diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 8c0b5486b9..21bd16ef00 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -1251,6 +1251,8 @@ setup_connection(Archive *AH, const char *dumpencoding, ExecuteSqlStatement(AH, "SET lock_timeout = 0"); if (AH->remoteVersion >= 90600) ExecuteSqlStatement(AH, "SET idle_in_transaction_session_timeout = 0"); + if (AH->remoteVersion >= 170000) + ExecuteSqlStatement(AH, "SET transaction_timeout = 0"); /* * Quote all identifiers, if requested. diff --git a/src/bin/pg_rewind/libpq_source.c b/src/bin/pg_rewind/libpq_source.c index 417c74cfef..9cda3f3667 100644 --- a/src/bin/pg_rewind/libpq_source.c +++ b/src/bin/pg_rewind/libpq_source.c @@ -117,6 +117,7 @@ init_libpq_conn(PGconn *conn) run_simple_command(conn, "SET statement_timeout = 0"); run_simple_command(conn, "SET lock_timeout = 0"); run_simple_command(conn, "SET idle_in_transaction_session_timeout = 0"); + run_simple_command(conn, "SET transaction_timeout = 0"); /* * we don't intend to do any updates, put the connection in read-only mode diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 74bc2f97cb..b2d0f84252 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -91,6 +91,7 @@ extern PGDLLIMPORT volatile sig_atomic_t InterruptPending; extern PGDLLIMPORT volatile sig_atomic_t QueryCancelPending; extern PGDLLIMPORT volatile sig_atomic_t ProcDiePending; extern PGDLLIMPORT volatile sig_atomic_t IdleInTransactionSessionTimeoutPending; +extern PGDLLIMPORT volatile sig_atomic_t TransactionTimeoutPending; extern PGDLLIMPORT volatile sig_atomic_t IdleSessionTimeoutPending; extern PGDLLIMPORT volatile sig_atomic_t ProcSignalBarrierPending; extern PGDLLIMPORT volatile sig_atomic_t LogMemoryContextPending; diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index e87fd25d64..9dde9cbfdd 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -429,6 +429,7 @@ extern PGDLLIMPORT int DeadlockTimeout; extern PGDLLIMPORT int StatementTimeout; extern PGDLLIMPORT int LockTimeout; extern PGDLLIMPORT int IdleInTransactionSessionTimeout; +extern PGDLLIMPORT int TransactionTimeout; extern PGDLLIMPORT int IdleSessionTimeout; extern PGDLLIMPORT bool log_lock_waits; diff --git a/src/include/utils/timeout.h b/src/include/utils/timeout.h index 8a61853371..608a83d5a8 100644 --- a/src/include/utils/timeout.h +++ b/src/include/utils/timeout.h @@ -31,6 +31,7 @@ typedef enum TimeoutId STANDBY_TIMEOUT, STANDBY_LOCK_TIMEOUT, IDLE_IN_TRANSACTION_SESSION_TIMEOUT, + TRANSACTION_TIMEOUT, IDLE_SESSION_TIMEOUT, IDLE_STATS_UPDATE_TIMEOUT, CLIENT_CONNECTION_CHECK_TIMEOUT, diff --git a/src/test/isolation/Makefile b/src/test/isolation/Makefile index ade2256ed3..2bd06f8f15 100644 --- a/src/test/isolation/Makefile +++ b/src/test/isolation/Makefile @@ -62,7 +62,7 @@ installcheck: all $(pg_isolation_regress_installcheck) --schedule=$(srcdir)/isolation_schedule check: all - $(pg_isolation_regress_check) --schedule=$(srcdir)/isolation_schedule + $(pg_isolation_regress_check) timeouts # Non-default tests. It only makes sense to run these if set up to use # prepared transactions, via TEMP_CONFIG for the check case, or via the @@ -72,3 +72,6 @@ installcheck-prepared-txns: all temp-install check-prepared-txns: all temp-install $(pg_isolation_regress_check) --schedule=$(srcdir)/isolation_schedule prepared-transactions prepared-transactions-cic + +check-timeouts: all temp-install + $(pg_isolation_regress_check) timeouts diff --git a/src/test/isolation/expected/timeouts.out b/src/test/isolation/expected/timeouts.out index 9328676f1c..5b06148cee 100644 --- a/src/test/isolation/expected/timeouts.out +++ b/src/test/isolation/expected/timeouts.out @@ -1,4 +1,4 @@ -Parsed test spec with 2 sessions +Parsed test spec with 6 sessions starting permutation: rdtbl sto locktbl step rdtbl: SELECT * FROM accounts; @@ -79,3 +79,64 @@ step slto: SET lock_timeout = '10s'; SET statement_timeout = '10ms'; step update: DELETE FROM accounts WHERE accountid = 'checking'; <waiting ...> step update: <... completed> ERROR: canceling statement due to statement timeout + +starting permutation: stto s3_begin sleep s3_check abort +step stto: SET statement_timeout = '1ms'; SET transaction_timeout = '1s'; +step s3_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step sleep: SELECT pg_sleep(0.01); +ERROR: canceling statement due to statement timeout +step s3_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s3'; +count +----- + 1 +(1 row) + +step abort: ABORT; + +starting permutation: tsto s3_begin wait_check s3_check +step tsto: SET statement_timeout = '1s'; SET transaction_timeout = '1ms'; +step s3_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step wait_check: SELECT pg_sleep(0.01); +pg_sleep +-------- + +(1 row) + +step s3_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s3'; +count +----- + 0 +(1 row) + + +starting permutation: itto s4_begin wait_check s4_check +step itto: SET idle_in_transaction_session_timeout = '1ms'; SET transaction_timeout = '1s'; +step s4_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step wait_check: SELECT pg_sleep(0.01); +pg_sleep +-------- + +(1 row) + +step s4_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s4'; +count +----- + 0 +(1 row) + + +starting permutation: tito s5_begin wait_check s5_check +step tito: SET idle_in_transaction_session_timeout = '1s'; SET transaction_timeout = '1ms'; +step s5_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step wait_check: SELECT pg_sleep(0.01); +pg_sleep +-------- + +(1 row) + +step s5_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s5'; +count +----- + 0 +(1 row) + diff --git a/src/test/isolation/specs/timeouts.spec b/src/test/isolation/specs/timeouts.spec index c747b4ae28..0cca6ff147 100644 --- a/src/test/isolation/specs/timeouts.spec +++ b/src/test/isolation/specs/timeouts.spec @@ -27,6 +27,27 @@ step locktbl { LOCK TABLE accounts; } step update { DELETE FROM accounts WHERE accountid = 'checking'; } teardown { ABORT; } +session s3 +step s3_begin { BEGIN ISOLATION LEVEL READ COMMITTED; } +step stto { SET statement_timeout = '1ms'; SET transaction_timeout = '1s'; } +step tsto { SET statement_timeout = '1s'; SET transaction_timeout = '1ms'; } +step sleep { SELECT pg_sleep(0.01); } +step abort { ABORT; } + +session s4 +step s4_begin { BEGIN ISOLATION LEVEL READ COMMITTED; } +step itto { SET idle_in_transaction_session_timeout = '1ms'; SET transaction_timeout = '1s'; } + +session s5 +step s5_begin { BEGIN ISOLATION LEVEL READ COMMITTED; } +step tito { SET idle_in_transaction_session_timeout = '1s'; SET transaction_timeout = '1ms'; } + +session s6 +step wait_check { SELECT pg_sleep(0.01); } +step s3_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s3'; } +step s4_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s4'; } +step s5_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s5'; } + # It's possible that the isolation tester will not observe the final # steps as "waiting", thanks to the relatively short timeouts we use. # We can ensure consistent test output by marking those steps with (*). @@ -47,3 +68,12 @@ permutation wrtbl lto update(*) permutation wrtbl lsto update(*) # statement timeout expires first, row-level lock permutation wrtbl slto update(*) + +# statement timeout expires first +permutation stto s3_begin sleep s3_check abort +# transaction timeout expires first, session s3 FATAL-out +permutation tsto s3_begin wait_check s3_check +# idle in transaction timeout expires first, session s4 FATAL-out +permutation itto s4_begin wait_check s4_check +# transaction timeout expires first, session s5 FATAL-out +permutation tito s5_begin wait_check s5_check base-commit: 3e2e0d5ad7fcb89d18a71cbfc885ef184e1b6f2e -- 2.41.0
>From 95133524aaeaf84733d6bb12a42d3e27aea85c16 Mon Sep 17 00:00:00 2001 From: japinli <japi...@hotmail.com> Date: Sat, 23 Dec 2023 11:04:25 +0800 Subject: [PATCH v16 2/2] Try to enable transaction_timeout before next command --- src/backend/tcop/postgres.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index a2611cf8e6..96161eb7ab 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4513,6 +4513,11 @@ PostgresMain(const char *dbname, const char *username) enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, IdleInTransactionSessionTimeout); } + + /* Schedule or reschedule transaction timeout */ + if (TransactionTimeout > 0 && !get_timeout_active(TRANSACTION_TIMEOUT)) + enable_timeout_after(TRANSACTION_TIMEOUT, + TransactionTimeout); } else if (IsTransactionOrTransactionBlock()) { @@ -4527,6 +4532,11 @@ PostgresMain(const char *dbname, const char *username) enable_timeout_after(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, IdleInTransactionSessionTimeout); } + + /* Schedule or reschedule transaction timeout */ + if (TransactionTimeout > 0 && !get_timeout_active(TRANSACTION_TIMEOUT)) + enable_timeout_after(TRANSACTION_TIMEOUT, + TransactionTimeout); } else { -- 2.41.0