Hi team,

One of our customers recently encountered an issue with PostgreSQL's
pg_cron and VACUUM ANALYZE. They had configured a table with
vacuum_truncate=false to prevent exclusive lock contention, assuming
this would apply globally. However, VACUUM ANALYZE executed across the
entire database doesn't honor this table-specific setting, though
autovacuum does.

I investigated the code and found a small bug with how we're passing
the VacuumParams pointer.

The call flow is
ExecVacuum -> vacuum -> vacuum_rel

The initial VaccumParams pointer is set in ExecVacuum
In vacuum_rel, this pointer might change because it needs to determine
whether to truncate and perform index_cleanup.

Vacuuming a single table works as expected because the options are
applied at the table level. However, when vacuuming multiple tables,
the second table reuses the modified parameters set by the first
table's vacuum_rel.

We can easy repro that with following SQL and same with index_cleanup:
create table test(id int);
create table test_1(id int) with (vacuum_truncate=false);
insert into test select generate_series(1,1000);
insert into test_1 select generate_series(1,1000);
delete from test;
delete from test_1;
vacuum (analyze) test_1, test;
postgres=# \dt+
                                   List of relations
 Schema |  Name  | Type  |  Owner   | Persistence | Access method |
Size  | Description
--------+--------+-------+----------+-------------+---------------+-------+-------------
 public | test   | table | postgres | permanent   | heap          | 72 kB |
 public | test_1 | table | postgres | permanent   | heap          | 72 kB |
(2 rows)

I've implemented a fix and included a regression test in the patch.

Thanks,
Shihao

Attachment: vacuum_tables_options.patch
Description: Binary data

Reply via email to