From 1ed73bb8ee489483aac5522b417815d743141cc0 Mon Sep 17 00:00:00 2001 From: "Andrey M. Borodin" Date: Fri, 29 Dec 2023 14:54:02 +0500 Subject: [PATCH v21 2/4] Add better tests for transaction_timeout: 1. Check COMMIT AND CHAIN 2. Check termination of active and idle queries 3. Check timeout reschedult 4. Check that timeout is not rescheduled by new queries --- src/test/isolation/Makefile | 3 + src/test/isolation/expected/timeouts.out | 123 ++++++++++++++++++++--- src/test/isolation/specs/timeouts.spec | 74 +++++++++----- 3 files changed, 163 insertions(+), 37 deletions(-) diff --git a/src/test/isolation/Makefile b/src/test/isolation/Makefile index ade2256ed3..482bb31949 100644 --- a/src/test/isolation/Makefile +++ b/src/test/isolation/Makefile @@ -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 cabe28f2c8..a500e9ab91 100644 --- a/src/test/isolation/expected/timeouts.out +++ b/src/test/isolation/expected/timeouts.out @@ -1,4 +1,5 @@ -Parsed test spec with 6 sessions +unused step name: s6_sleep +Parsed test spec with 8 sessions starting permutation: rdtbl sto locktbl step rdtbl: SELECT * FROM accounts; @@ -80,39 +81,133 @@ step update: DELETE FROM accounts WHERE accountid = 'checking'; step update: <... completed> ERROR: canceling statement due to statement timeout -starting permutation: stt1_set stt1_begin sleep_here stt2_set stt2_begin sleep_there stt3_check_stt2 itt4_set itt4_begin sleep_there stt3_check_itt4 -step stt1_set: SET transaction_timeout = '1ms'; -step stt1_begin: BEGIN ISOLATION LEVEL READ COMMITTED; -step sleep_here: SELECT pg_sleep(1); +starting permutation: stto s3_begin s3_sleep s3_check s3_abort +step stto: SET statement_timeout = '1ms'; SET transaction_timeout = '1s'; +step s3_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step s3_sleep: SELECT pg_sleep(0.1); +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 s3_abort: ABORT; + +starting permutation: tsto s3_begin s3_sleep s3_check +step tsto: SET statement_timeout = '1s'; SET transaction_timeout = '1ms'; +step s3_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step s3_sleep: SELECT pg_sleep(0.1); FATAL: terminating connection due to transaction timeout server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request. -step stt2_set: SET transaction_timeout = '1ms'; -step stt2_begin: BEGIN ISOLATION LEVEL READ COMMITTED; -step sleep_there: SELECT pg_sleep(0.1); +step s3_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s3'; +count +----- + 0 +(1 row) + + +starting permutation: itto s4_begin checker_sleep s4_check +step itto: SET idle_in_transaction_session_timeout = '1ms'; SET transaction_timeout = '1s'; +step s4_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step checker_sleep: SELECT pg_sleep(0.1); +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 checker_sleep s5_check +step tito: SET idle_in_transaction_session_timeout = '1s'; SET transaction_timeout = '1ms'; +step s5_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step checker_sleep: SELECT pg_sleep(0.1); +pg_sleep +-------- + +(1 row) + +step s5_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s5'; +count +----- + 0 +(1 row) + + +starting permutation: s6_begin s6_tt checker_sleep s6_check +step s6_begin: BEGIN ISOLATION LEVEL READ COMMITTED; +step s6_tt: SET statement_timeout = '1s'; SET transaction_timeout = '1ms'; +step checker_sleep: SELECT pg_sleep(0.1); pg_sleep -------- (1 row) -step stt3_check_stt2: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/stt2' +step s6_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s6'; count ----- 0 (1 row) -step itt4_set: SET idle_in_transaction_session_timeout = '1ms'; SET statement_timeout = '10s'; SET lock_timeout = '10s'; SET transaction_timeout = '10s'; -step itt4_begin: BEGIN ISOLATION LEVEL READ COMMITTED; -step sleep_there: SELECT pg_sleep(0.1); + +starting permutation: s7_begin s7_sleep s7_commit_and_chain s7_sleep s7_check s7_abort +step s7_begin: + BEGIN ISOLATION LEVEL READ COMMITTED; + SET transaction_timeout = '150ms'; + +step s7_sleep: SELECT pg_sleep(0.1); +pg_sleep +-------- + +(1 row) + +step s7_commit_and_chain: COMMIT AND CHAIN; +step s7_sleep: SELECT pg_sleep(0.1); +pg_sleep +-------- + +(1 row) + +step s7_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s7'; +count +----- + 1 +(1 row) + +step s7_abort: ABORT; + +starting permutation: s7_begin s7_sleep s7_select_1 checker_sleep s7_check +step s7_begin: + BEGIN ISOLATION LEVEL READ COMMITTED; + SET transaction_timeout = '150ms'; + +step s7_sleep: SELECT pg_sleep(0.1); +pg_sleep +-------- + +(1 row) + +step s7_select_1: SELECT 1; +?column? +-------- + 1 +(1 row) + +step checker_sleep: SELECT pg_sleep(0.1); pg_sleep -------- (1 row) -step stt3_check_itt4: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/itt4' -step stt3_check_itt4: <... completed> +step s7_check: SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s7'; count ----- 0 diff --git a/src/test/isolation/specs/timeouts.spec b/src/test/isolation/specs/timeouts.spec index 2772939b6b..dc47d4f362 100644 --- a/src/test/isolation/specs/timeouts.spec +++ b/src/test/isolation/specs/timeouts.spec @@ -18,7 +18,7 @@ step wrtbl { UPDATE accounts SET balance = balance + 100; } teardown { ABORT; } session s2 -setup { SET transaction_timeout = '10s'; SET idle_in_transaction_session_timeout = '10s'; BEGIN ISOLATION LEVEL READ COMMITTED; } +setup { BEGIN ISOLATION LEVEL READ COMMITTED; } step sto { SET statement_timeout = '10ms'; } step lto { SET lock_timeout = '10ms'; } step lsto { SET lock_timeout = '10ms'; SET statement_timeout = '10s'; } @@ -27,28 +27,45 @@ step locktbl { LOCK TABLE accounts; } step update { DELETE FROM accounts WHERE accountid = 'checking'; } teardown { ABORT; } -session stt1 -# enable statement_timeout to check interaction -setup { SET statement_timeout = '10s'; SET lock_timeout = '10s'; } -step stt1_set { SET transaction_timeout = '1ms'; } -step stt1_begin { BEGIN ISOLATION LEVEL READ COMMITTED; } -step sleep_here { SELECT pg_sleep(1); } +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 s3_sleep { SELECT pg_sleep(0.1); } +step s3_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 stt2 -setup { SET statement_timeout = '10s'; SET lock_timeout = '10s'; } -step stt2_set { SET transaction_timeout = '1ms'; } -step stt2_begin { BEGIN ISOLATION LEVEL READ COMMITTED; } -# Session stt2 is terminated in the background. However, isolation tester needs a step to observe it. +session s6 +step s6_begin { BEGIN ISOLATION LEVEL READ COMMITTED; } +step s6_tt { SET statement_timeout = '1s'; SET transaction_timeout = '1ms'; } +step s6_sleep { SELECT pg_sleep(0.1); } -session stt3 -step sleep_there{ SELECT pg_sleep(0.1); } -# Observe that stt2\itt4 died -step stt3_check_stt2 { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/stt2' } -step stt3_check_itt4 { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/itt4' } +session s7 +step s7_begin +{ + BEGIN ISOLATION LEVEL READ COMMITTED; + SET transaction_timeout = '150ms'; +} +step s7_commit_and_chain { COMMIT AND CHAIN; } +# to test that quick query does not restart transaction_timeout +step s7_select_1 { SELECT 1; } +step s7_sleep { SELECT pg_sleep(0.1); } +step s7_abort { ABORT; } -session itt4 -step itt4_set { SET idle_in_transaction_session_timeout = '1ms'; SET statement_timeout = '10s'; SET lock_timeout = '10s'; SET transaction_timeout = '10s'; } -step itt4_begin { BEGIN ISOLATION LEVEL READ COMMITTED; } +session checker +step checker_sleep { SELECT pg_sleep(0.1); } +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'; } +step s6_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s6'; } +step s7_check { SELECT count(*) FROM pg_stat_activity WHERE application_name = 'isolation/timeouts/s7'; } # It's possible that the isolation tester will not observe the final # steps as "waiting", thanks to the relatively short timeouts we use. @@ -71,6 +88,17 @@ permutation wrtbl lsto update(*) # statement timeout expires first, row-level lock permutation wrtbl slto update(*) -# timeout of active query, idle transaction timeout -permutation stt1_set stt1_begin sleep_here stt2_set stt2_begin sleep_there stt3_check_stt2 itt4_set itt4_begin sleep_there stt3_check_itt4(*) -# can't run tests after this, sessions stt1, stt2, and itt4 are expected to FATAL-out +# statement timeout expires first +permutation stto s3_begin s3_sleep s3_check s3_abort +# transaction timeout expires first, session s3 FATAL-out +permutation tsto s3_begin s3_sleep s3_check +# idle in transaction timeout expires first, session s4 FATAL-out +permutation itto s4_begin checker_sleep s4_check +# transaction timeout expires first, session s5 FATAL-out +permutation tito s5_begin checker_sleep s5_check +# transaction timeout can be schedule amid transaction, session s6 FATAL-out +permutation s6_begin s6_tt checker_sleep s6_check +# COMMIT AND CHAIN must restart transaction timeout +permutation s7_begin s7_sleep s7_commit_and_chain s7_sleep s7_check s7_abort +# transaction timeout expires in presence of query flow, session s7 FATAL-out +permutation s7_begin s7_sleep s7_select_1 checker_sleep s7_check -- 2.37.1 (Apple Git-137.1)