mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Fix Parallel TID Range Scan rescans with a different TID range
0ca3b1697added support for parallel TID Range Scans. The range of blocks to scan is stored in the shared phs_startblock and phs_numblock fields by the first participant to start the scan, but table_block_parallelscan_reinitialize() didn't reset these, so every rescan of the Gather reused the block range of the first execution. This caused rows to be silently missed when a rescan used a different TID range, e.g: SELECT r.lo, (SELECT count(*) FROM t WHERE ctid >= (SELECT r.lo)) FROM (VALUES ('(30,0)'::tid), ('(10,0)'), ('(0,0)')) r(lo); Here we fix this by resetting both fields in table_block_parallelscan_reinitialize(). As a side effect, a rescanned Parallel Seq Scan using synchronized scans now gets a new start location, which is what a new scan would do anyway. The existing rescan test didn't exercise this, so add one that does. This was introduced in0ca3b1697, so backpatch to v19. Reported-by: Zsolt Parragi <zsolt.parragi@percona.com> Author: Zsolt Parragi <zsolt.parragi@percona.com> Author: David Rowley <dgrowleyml@gmail.com> Reviewed-by: David Rowley <dgrowleyml@gmail.com> Reviewed-by: shihao zhong <zhong950419@gmail.com> Discussion: https://postgr.es/m/CAN4CZFOoyCQE483YVGg07_Vr2MjFCTiCLUHUAFCwKqJAE=PN6w@mail.gmail.com Backpatch-through: 19
This commit is contained in:
@@ -395,6 +395,14 @@ table_block_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
|
||||
{
|
||||
ParallelBlockTableScanDesc bpscan = (ParallelBlockTableScanDesc) pscan;
|
||||
|
||||
/*
|
||||
* Reset the start block and block limit too. These are set by the first
|
||||
* participant to call table_block_parallelscan_startblock_init(), and a
|
||||
* rescan may want to scan a different range of blocks, e.g. a TID Range
|
||||
* Scan with different TID bounds.
|
||||
*/
|
||||
pg_atomic_write_u32(&bpscan->phs_startblock, InvalidBlockNumber);
|
||||
pg_atomic_write_u32(&bpscan->phs_numblock, InvalidBlockNumber);
|
||||
pg_atomic_write_u64(&bpscan->phs_nallocated, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -427,5 +427,36 @@ WHERE t.ctid < '(1,0)';
|
||||
(0,5) | 5
|
||||
(5 rows)
|
||||
|
||||
-- Parallel rescans with a different TID range on each rescan
|
||||
EXPLAIN (COSTS OFF)
|
||||
SELECT r.lo,
|
||||
(SELECT count(*) FROM parallel_tidrangescan t
|
||||
WHERE t.ctid >= (SELECT r.lo)) c
|
||||
FROM (VALUES ('(30,0)'::tid), ('(10,0)'), ('(0,0)')) r(lo);
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------
|
||||
Values Scan on "*VALUES*"
|
||||
SubPlan expr_1
|
||||
-> Finalize Aggregate
|
||||
InitPlan expr_2
|
||||
-> Result
|
||||
-> Gather
|
||||
Workers Planned: 4
|
||||
-> Partial Aggregate
|
||||
-> Parallel Tid Range Scan on parallel_tidrangescan t
|
||||
TID Cond: (ctid >= (InitPlan expr_2).col1)
|
||||
(10 rows)
|
||||
|
||||
SELECT r.lo,
|
||||
(SELECT count(*) FROM parallel_tidrangescan t
|
||||
WHERE t.ctid >= (SELECT r.lo)) c
|
||||
FROM (VALUES ('(30,0)'::tid), ('(10,0)'), ('(0,0)')) r(lo);
|
||||
lo | c
|
||||
--------+-----
|
||||
(30,0) | 50
|
||||
(10,0) | 150
|
||||
(0,0) | 200
|
||||
(3 rows)
|
||||
|
||||
ROLLBACK;
|
||||
RESET enable_seqscan;
|
||||
|
||||
@@ -153,5 +153,17 @@ SELECT t.ctid,t2.c FROM parallel_tidrangescan t,
|
||||
LATERAL (SELECT count(*) c FROM parallel_tidrangescan t2 WHERE t2.ctid <= t.ctid) t2
|
||||
WHERE t.ctid < '(1,0)';
|
||||
|
||||
-- Parallel rescans with a different TID range on each rescan
|
||||
EXPLAIN (COSTS OFF)
|
||||
SELECT r.lo,
|
||||
(SELECT count(*) FROM parallel_tidrangescan t
|
||||
WHERE t.ctid >= (SELECT r.lo)) c
|
||||
FROM (VALUES ('(30,0)'::tid), ('(10,0)'), ('(0,0)')) r(lo);
|
||||
|
||||
SELECT r.lo,
|
||||
(SELECT count(*) FROM parallel_tidrangescan t
|
||||
WHERE t.ctid >= (SELECT r.lo)) c
|
||||
FROM (VALUES ('(30,0)'::tid), ('(10,0)'), ('(0,0)')) r(lo);
|
||||
|
||||
ROLLBACK;
|
||||
RESET enable_seqscan;
|
||||
|
||||
Reference in New Issue
Block a user