Re: HOT chain validation in verify_heapam()

Поиск
Список
Период
Сортировка
От Robert Haas
Тема Re: HOT chain validation in verify_heapam()
Дата
Msg-id CA+TgmoYqPdY+_2NDABkkMVA4fya5_vbmnXcQc6ytMYNghVKfeg@mail.gmail.com
обсуждение исходный текст
Ответ на Re: HOT chain validation in verify_heapam()  (Andres Freund <andres@anarazel.de>)
Список pgsql-hackers
On Wed, Mar 22, 2023 at 4:45 PM Andres Freund <andres@anarazel.de> wrote:
> At the very least there's missing verification that tids actually exists in the
> "Update chain validation" loop, leading to:
> TRAP: failed Assert("ItemIdHasStorage(itemId)"), File:
"../../../../home/andres/src/postgresql/src/include/storage/bufpage.h",Line: 355, PID: 645093 
>
> Which makes sense - the earlier loop adds t_ctid to the successor array, which
> we then query without checking if there still is such a tid on the page.

Ah, crap. If the /* Perform tuple checks loop */ finds a redirect line
pointer, it verifies that the target is between FirstOffsetnNumber and
maxoff before setting lp_valid[ctx.offnum] = true. But in the case
where it's a CTID link, the equivalent checks are missing. We could
fix that like this:

--- a/contrib/amcheck/verify_heapam.c
+++ b/contrib/amcheck/verify_heapam.c
@@ -543,7 +543,8 @@ verify_heapam(PG_FUNCTION_ARGS)
              */
             nextblkno = ItemPointerGetBlockNumber(&(ctx.tuphdr)->t_ctid);
             nextoffnum = ItemPointerGetOffsetNumber(&(ctx.tuphdr)->t_ctid);
-            if (nextblkno == ctx.blkno && nextoffnum != ctx.offnum)
+            if (nextblkno == ctx.blkno && nextoffnum != ctx.offnum &&
+                nextoffnum >= FirstOffsetNumber && nextoffnum <= maxoff)
                 successor[ctx.offnum] = nextoffnum;
         }

> I suspect we don't just need a !ItemIdIsUsed(), but also a check gainst the
> max offset on the page.

I don't see why we need an ItemIdIsUsed check any place where we don't
have one already. lp_valid[x] can't be true if the item x isn't used,
unless we're referencing off the initialized portion of the array,
which we shouldn't do.

> WRT these failures:
> non-heap-only update produced a heap-only tuple at offset 20
>
> I think that's largely a consequence of HeapTupleHeaderIsHotUpdated()'s
> definition:
> /*
>  * Note that we stop considering a tuple HOT-updated as soon as it is known
>  * aborted or the would-be updating transaction is known aborted.  For best
>  * efficiency, check tuple visibility before using this macro, so that the
>  * INVALID bits will be as up to date as possible.
>  */
> #define HeapTupleHeaderIsHotUpdated(tup) \
> ( \
>         ((tup)->t_infomask2 & HEAP_HOT_UPDATED) != 0 && \
>         ((tup)->t_infomask & HEAP_XMAX_INVALID) == 0 && \
>         !HeapTupleHeaderXminInvalid(tup) \
> )

Yeah, it's not good that we're looking at the hint bit or the xmin
there -- it should just be checking the infomask2 bit and nothing
else, I think.

--
Robert Haas
EDB: http://www.enterprisedb.com



В списке pgsql-hackers по дате отправления:

Предыдущее
От: Peter Eisentraut
Дата:
Сообщение: Re: Transparent column encryption
Следующее
От: Nazir Bilal Yavuz
Дата:
Сообщение: Re: Refactor calculations to use instr_time