postgres.git / summary / log / commit / refs

commit    ad8c86d22cbd043cfb48cc3c18e43c4f267b2eb0
Author:   Michael Paquier <michael@paquier.xyz>
Date:     Wed Mar 04 07:30:51 2026 +0000

    Fix rare instability in recovery TAP test 009_twophase
    
    The phase of the test where we want to check that 2PC transactions
    prepared on a primary can be committed on a promoted standby relied on
    an immediate stop of the primary.  This logic has a race condition: it
    could be possible that some records (most likely standby snapshot
    records) are generated on the primary before it finishes its shutdown,
    without the promoted standby know about them.  When the primary is
    recycled as new standby, the test could fail because of a timeline fork
    as an effect of these extra records.
    
    This fix takes care of the instability by doing a clean stop of the
    primary instead of a teardown (aka immediate stop), so as all records
    generated on the primary are sent to the promoted standby and flushed
    there.  There is no need for a teardown of the primary in this test
    scenario: the commit of 2PC transactions on a promoted standby do not
    care about the state of the primary, only of the standby.
    
    This race is very hard to hit in practice, even slow buildfarm members
    like skink have a very low rate of reproduction.  Alexander Lakhin has
    come up with a recipe to improve the reproduction rate a lot:
    - Enable -DWAL_DEBUG.
    - Patch the bgwriter so as standby snapshots are generated every
    milliseconds.
    - Run 009_twophase tests under heavy parallelism.
    
    With this method, the failure appears after a couple of iterations.
    With the fix in place, I have been able to run more than 50 iterations
    of the parallel test sequence, without seeing a failure.
    
    Issue introduced in 30820982b295, due to a copy-pasto coming from the
    surrounding tests.  Thanks also to Hayato Kuroda for digging into the
    details of the failure.  He has proposed a fix different than the one of
    this commit.  Unfortunately, it relied on injection points, feature only
    available in v17.  The solution of this commit is simpler, and can be
    applied to v14~v16.
    
    Reported-by: Alexander Lakhin <exclusion@gmail.com>
    Discussion: https://postgr.es/m/b0102688-6d6c-c86a-db79-e0e91d245b1a@gmail.com
    Backpatch-through: 14


src/test/recovery/t/009_twophase.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/recovery/t/009_twophase.pl b/src/test/recovery/t/009_twophase.pl index 879e493b5b8..aa73d3e106c 100644 --- a/src/test/recovery/t/009_twophase.pl +++ b/src/test/recovery/t/009_twophase.pl @@ -222,7 +222,7 @@ $cur_primary->psql( SAVEPOINT s1; INSERT INTO t_009_tbl VALUES (22, 'issued to ${cur_primary_name}'); PREPARE TRANSACTION 'xact_009_10';"); -$cur_primary->teardown_node; +$cur_primary->stop; $cur_standby->promote; # change roles [parent: 7c1849311e49]