pgsql: Don't add non-existent pages to bitmap from BRIN

From: Tomas Vondra <tomas(dot)vondra(at)postgresql(dot)org>
To: pgsql-committers(at)lists(dot)postgresql(dot)org
Subject: pgsql: Don't add non-existent pages to bitmap from BRIN
Date: 2021-04-07 13:58:55
Message-ID: E1lU8hr-0007vj-Es@gemulon.postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-committers

Don't add non-existent pages to bitmap from BRIN

The code in bringetbitmap() simply added the whole matching page range
to the TID bitmap, as determined by pages_per_range, even if some of the
pages were beyond the end of the heap. The query then might fail with
an error like this:

ERROR: could not open file "base/20176/20228.2" (target block
262144): previous segment is only 131021 blocks

In this case, the relation has 262093 pages (131072 and 131021 pages),
but we're trying to acess block 262144, i.e. first block of the 3rd
segment. At that point _mdfd_getseg() notices the preceding segment is
incomplete, and fails.

Hitting this in practice is rather unlikely, because:

* Most indexes use power-of-two ranges, so segments and page ranges
align perfectly (segment end is also a page range end).

* The table size has to be just right, with the last segment being
almost full - less than one page range from full segment, so that the
last page range actually crosses the segment boundary.

* Prefetch has to be enabled. The regular page access checks that
pages are not beyond heap end, but prefetch does not. On older
releases (before 12) the execution stops after hitting the first
non-existent page, so the prefetch distance has to be sufficient
to reach the first page in the next segment to trigger the issue.
Since 12 it's enough to just have prefetch enabled, the prefetch
distance does not matter.

Fixed by not adding non-existent pages to the TID bitmap. Backpatch
all the way back to 9.6 (BRIN indexes were introduced in 9.5, but that
release is EOL).

Backpatch-through: 9.6

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/23607a8156d595522c232ff3933d77041d3adaa1

Modified Files
--------------
src/backend/access/brin/brin.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Browse pgsql-committers by date

  From Date Subject
Next Message Tomas Vondra 2021-04-07 14:00:57 pgsql: Don't add non-existent pages to bitmap from BRIN
Previous Message Peter Eisentraut 2021-04-07 13:17:14 pgsql: libpq: Set Server Name Indication (SNI) for SSL connections