pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Alexander Lakhin <exclusion@gmail.com>
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: Test tidscan,sql is not immune to autovacuum in v14
Date: Wed, 19 Aug 2026 23:00:01 +0300
Message-ID: <f5d1f4c2-6224-4797-be17-c86e77f96c9c@gmail.com> (raw)

Hello hackers,

I spotted a very rare test failure (a single one in two years, at least)
generated by basilisk:
      tidscan                      ... FAILED       34 ms
...
diff -U3 /mnt/build/REL_14_STABLE/pgsql.build/../pgsql/src/test/regress/expected/tidscan.out 
/mnt/build/REL_14_STABLE/pgsql.build/src/test/regress/results/tidscan.out
--- /mnt/build/REL_14_STABLE/pgsql.build/../pgsql/src/test/regress/expected/tidscan.out
+++ /mnt/build/REL_14_STABLE/pgsql.build/src/test/regress/results/tidscan.out
@@ -242,10 +242,10 @@
  ----------------------------------------
   Aggregate
     ->  Hash Join
-         Hash Cond: (t1.ctid = t2.ctid)
-         ->  Seq Scan on tenk1 t1
+         Hash Cond: (t2.ctid = t1.ctid)
+         ->  Seq Scan on tenk1 t2
           ->  Hash
-               ->  Seq Scan on tenk1 t2
+               ->  Seq Scan on tenk1 t1
  (6 rows)

  SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid;

and was intrigued enough to find a reliable reproducer for it.
With the following modification:
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -188,6 +188,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
                 estimate_rel_size(relation, rel->attr_widths - rel->min_attr,
&rel->pages, &rel->tuples, &rel->allvisfrac);

+char *name = get_rel_name(relationObjectId); if (name != NULL && strcmp(name, "tenk1") == 0) pg_usleep(100000);
         /* Retrieve the parallel_workers reloption, or -1 if not set. */
         rel->rel_parallel_workers = RelationGetParallelWorkers(relation, -1);

and
test: tidscan analyze
in parallel_schedule (the full patch is attached), I get:
parallel group (2 tests):  analyze tidscan
      tidscan                      ... FAILED      900 ms
      analyze                      ... ok           63 ms

(The basilisk's log contain no autovacuum messages, but I guess it was
automatic analyze that processed tenk1 in the very lucky moment.)

Given the current statistics, we won't see failures of this ilk anymore,
because it is not reproduced in REL_15_STABLE..master, due to 74388a1ac +
4496020e6, which resulted in a different reltuples value returned for tenk1
during sanity_check/VACUUM and that indirectly affected the plan change.

[1] https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=basilisk&dt=2026-06-15%2006%3A07%3A09

Best regards,
Alexander

Attachments:

  [text/x-patch] repro-tidscan-failure.patch (1.8K, ../f5d1f4c2-6224-4797-be17-c86e77f96c9c@gmail.com/2-repro-tidscan-failure.patch)
  download | inline diff:
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index e7856b54bbb..6df0ed4da36 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -167,6 +167,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 		estimate_rel_size(relation, rel->attr_widths - rel->min_attr,
 						  &rel->pages, &rel->tuples, &rel->allvisfrac);
 
+char *name = get_rel_name(relationObjectId); if (name != NULL && strcmp(name, "tenk1") == 0) pg_usleep(100000);
 	/* Retrieve the parallel_workers reloption, or -1 if not set. */
 	rel->rel_parallel_workers = RelationGetParallelWorkers(relation, -1);
 
diff --git a/src/test/regress/expected/analyze.out b/src/test/regress/expected/analyze.out
new file mode 100644
index 00000000000..a0b9c748e86
--- /dev/null
+++ b/src/test/regress/expected/analyze.out
@@ -0,0 +1 @@
+ANALYZE tenk1;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 52ef93828fa..68f293510f0 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -86,7 +86,9 @@ test: brin_bloom brin_multi
 # ----------
 # Another group of parallel tests
 # ----------
-test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort
+test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidrangescan collate.icu.utf8 incremental_sort
+
+test: tidscan analyze
 
 # rules cannot run concurrently with any test that creates
 # a view or rule in the public schema
diff --git a/src/test/regress/sql/analyze.sql b/src/test/regress/sql/analyze.sql
new file mode 100644
index 00000000000..a0b9c748e86
--- /dev/null
+++ b/src/test/regress/sql/analyze.sql
@@ -0,0 +1 @@
+ANALYZE tenk1;


view thread (8+ messages)  latest in thread

Message-ID: <f5d1f4c2-6224-4797-be17-c86e77f96c9c@gmail.com>
Permalink:  ../f5d1f4c2-6224-4797-be17-c86e77f96c9c@gmail.com/
Also on:    postgresql.org/message-id/f5d1f4c2-6224-4797-be17-c86e77f96c9c@gmail.com

 ·  · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: exclusion@gmail.com
  Subject: Re: Test tidscan,sql is not immune to autovacuum in v14
  In-Reply-To: <f5d1f4c2-6224-4797-be17-c86e77f96c9c@gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox