On Thu, Mar 18, 2021, at 8:34 PM, Tomas Vondra wrote: > Well, that's better, bit it still does not do the trick on the 32-bit > machine - in that case a 1000 rows with int4 still fit into work_mem, so > the temp file is not created. Per my experiments about 1040 rows are > needed - soooo close ;-) So let's make it 2000. My 32-bit laptop needs some repairs so I blindly chose 1k rows.
> We might as well check that the temp file actually exists, before > killing the backend. Just to be sure. Do you mean with remove_temp_files_after_crash = on? New version attached. -- Euler Taveira EDB https://www.enterprisedb.com/
diff --git a/src/test/recovery/t/022_crash_temp_files.pl b/src/test/recovery/t/022_crash_temp_files.pl index c37b227770..38e935d641 100644 --- a/src/test/recovery/t/022_crash_temp_files.pl +++ b/src/test/recovery/t/022_crash_temp_files.pl @@ -5,9 +5,8 @@ use PostgresNode; use TestLib; use Test::More; use Config; -use Time::HiRes qw(usleep); -plan tests => 9; +plan tests => 10; # To avoid hanging while expecting some specific input from a psql @@ -33,8 +32,7 @@ $node->safe_psql( # create table, insert rows $node->safe_psql( 'postgres', - q[CREATE TABLE tab_crash (a text); - INSERT INTO tab_crash (a) SELECT gen_random_uuid() FROM generate_series(1, 500);]); + q[CREATE TABLE tab_crash (a integer UNIQUE);]); # Run psql, keeping session alive, so we have an alive backend to kill. my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', ''); @@ -62,6 +60,32 @@ chomp($pid); $killme_stdout = ''; $killme_stderr = ''; +# Open a 2nd session that will block the 1st session. The UNIQUE constraint +# will prevent the temporary file from the 1st session to be removed. +my ($killme_stdin2, $killme_stdout2, $killme_stderr2) = ('', '', ''); +my $killme2 = IPC::Run::start( + [ + 'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d', + $node->connstr('postgres') + ], + '<', + \$killme_stdin2, + '>', + \$killme_stdout2, + '2>', + \$killme_stderr2, + $psql_timeout); + +# Insert one tuple and leave the transaction open +$killme_stdin2 .= q[ +BEGIN; +SELECT $$insert-tuple-to-lock-next-insert$$; +INSERT INTO tab_crash (a) VALUES(1); +]; +pump_until($killme2, \$killme_stdout2, qr/insert-tuple-to-lock-next-insert/m); +$killme_stdout2 = ''; +$killme_stderr2 = ''; + # Run the query that generates a temporary file and that will be killed before # it finishes. Since the query that generates the temporary file does not # return before the connection is killed, use a SELECT before to trigger @@ -69,15 +93,18 @@ $killme_stderr = ''; $killme_stdin .= q[ BEGIN; SELECT $$in-progress-before-sigkill$$; -WITH foo AS (SELECT a FROM tab_crash ORDER BY a) SELECT a, pg_sleep(1) FROM foo; +INSERT INTO tab_crash (a) SELECT i FROM generate_series(1, 2000) s(i); ]; ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m), - 'select in-progress-before-sigkill'); + 'insert in-progress-before-sigkill'); $killme_stdout = ''; $killme_stderr = ''; -# Wait some time so the temporary file is generated by SELECT -usleep(10_000); +# Check for the existence of a temporary file +is($node->safe_psql( + 'postgres', + 'SELECT COUNT(1) FROM pg_ls_dir($$base/pgsql_tmp$$)'), + qq(1), 'one temporary file'); # Kill with SIGKILL my $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid); @@ -85,6 +112,7 @@ is($ret, 0, 'killed process with KILL'); # Close psql session $killme->finish; +$killme2->finish; # Wait till server restarts $node->poll_query_until('postgres', 'SELECT 1', '1'); @@ -118,6 +146,20 @@ chomp($pid); $killme_stdout = ''; $killme_stderr = ''; +# Restart the 2nd psql session +($killme_stdin2, $killme_stdout2, $killme_stderr2) = ('', '', ''); +$killme2->run(); + +# Insert one tuple and leave the transaction open +$killme_stdin2 .= q[ +BEGIN; +SELECT $$insert-tuple-to-lock-next-insert$$; +INSERT INTO tab_crash (a) VALUES(1); +]; +pump_until($killme2, \$killme_stdout2, qr/insert-tuple-to-lock-next-insert/m); +$killme_stdout2 = ''; +$killme_stderr2 = ''; + # Run the query that generates a temporary file and that will be killed before # it finishes. Since the query that generates the temporary file does not # return before the connection is killed, use a SELECT before to trigger @@ -125,22 +167,20 @@ $killme_stderr = ''; $killme_stdin .= q[ BEGIN; SELECT $$in-progress-before-sigkill$$; -WITH foo AS (SELECT a FROM tab_crash ORDER BY a) SELECT a, pg_sleep(1) FROM foo; +INSERT INTO tab_crash (a) SELECT i FROM generate_series(1, 2000) s(i); ]; ok(pump_until($killme, \$killme_stdout, qr/in-progress-before-sigkill/m), - 'select in-progress-before-sigkill'); + 'insert in-progress-before-sigkill'); $killme_stdout = ''; $killme_stderr = ''; -# Wait some time so the temporary file is generated by SELECT -usleep(10_000); - # Kill with SIGKILL $ret = TestLib::system_log('pg_ctl', 'kill', 'KILL', $pid); is($ret, 0, 'killed process with KILL'); # Close psql session $killme->finish; +$killme2->finish; # Wait till server restarts $node->poll_query_until('postgres', 'SELECT 1', '1');