BRIN: Handle concurrent desummarization properly

If a page range is desummarized at just the right time concurrently with
an index walk, BRIN would raise an error indicating index corruption.
This is scary and unhelpful; silently returning that the page range is
not summarized is sufficient reaction.

This bug was introduced by commit 975ad4e602 as additional protection
against a bug whose actual fix was elsewhere.  Backpatch equally.

Reported-By: Anastasia Lubennikova <a.lubennikova@postgrespro.ru>
Diagnosed-By: Alexander Lakhin <exclusion@gmail.com>
Discussion: https://postgr.es/m/2588667e-d07d-7e10-74e2-7e1e46194491@postgrespro.ru
Backpatch: 9.5 - master
This commit is contained in:
Alvaro Herrera 2020-08-12 15:33:36 -04:00
parent 3546cf8a7a
commit 1f42d35a1d
No known key found for this signature in database
GPG Key ID: 1C20ACB9D5C564AE
1 changed files with 10 additions and 3 deletions

View File

@ -282,10 +282,17 @@ brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk,
/* If we land on a revmap page, start over */
if (BRIN_IS_REGULAR_PAGE(page))
{
/*
* If the offset number is greater than what's in the page, it's
* possible that the range was desummarized concurrently. Just
* return NULL to handle that case.
*/
if (*off > PageGetMaxOffsetNumber(page))
ereport(ERROR,
(errcode(ERRCODE_INDEX_CORRUPTED),
errmsg_internal("corrupted BRIN index: inconsistent range map")));
{
LockBuffer(*buf, BUFFER_LOCK_UNLOCK);
return NULL;
}
lp = PageGetItemId(page, *off);
if (ItemIdIsUsed(lp))
{