Hello I found a bug in parallel TID range can: if the gather above it gets rescanned with different TID bounds, rows can go missing.
A simple way to reproduce it:
CREATE TABLE t (id int, pad text) WITH (fillfactor = 10);
INSERT INTO t SELECT i, repeat('x', 100) FROM generate_series(1, 200) i;
SET parallel_setup_cost = 0;
SET parallel_tuple_cost = 0;
SET min_parallel_table_scan_size = 0;
SET max_parallel_workers_per_gather = 4;
SELECT r.lo, (SELECT count(*) FROM t WHERE ctid >= (SELECT r.lo)) c
FROM (VALUES ('(30,0)'::tid), ('(10,0)'), ('(0,0)')) r(lo);
This should return 50, 150 and 200 (that's also what 18 returns,
without the parallel scan), but master and 19rc1 return 50 for all 3
rows.
The cause:
phs_startblock and phs_numblock in ParallelBlockTableScanDesc are set
by whichever participant calls
table_block_parallelscan_startblock_init() first, but
table_block_parallelscan_reinitialize() only resets phs_nallocated. So
every rescan scans the block range of the first execution, and the
per-tuple TID check then throws away anything outside the new range.
The attached patch resets both fields to InvalidBlockNumber in
table_block_parallelscan_reinitialize(), and adds a test that fails
without the fix.
v1-0001-Fix-Parallel-TID-Range-Scan-rescans-with-a-differ.patch
Description: Binary data
