回复:Re: PANIC: wrong buffer passed to visibilitymap_clear

From: 王伟(学弈) <rogers(dot)ww(at)alibaba-inc(dot)com>
To: "Peter Geoghegan" <pg(at)bowt(dot)ie>
Cc: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>, "pgsql-hackers" <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: 回复:Re: PANIC: wrong buffer passed to visibilitymap_clear
Date: 2022-07-26 09:51:07
Message-ID: 3a7f4285-bf43-4f94-b706-e9d98f5962c6.rogers.ww@alibaba-inc.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Fri, Jul 22, 2022 at 14:49 Peter Geoghegan wrote:
> The line numbers from your stack trace don't match up with> REL_14_STABLE. Is this actually a fork of Postgres 14? (Oh, looks like
> it's an old beta release.)

Yeah, I was testing on 14beta2 branch once. So I considered your
advices and test on REL_14_STABLE branch. But I'm not lucky
enough to repeat this core file during the past few days.

> It would also be helpful if you told us about the specific table
> involved. Though the important thing (the essential thing) is to test
> today's REL_14_STABLE. There have been *lots* of bug fixes since
> Postgres 14 beta2 was current.

Besides, the logic of heap_update and RelationGetBufferForTuple functions
are mostly same between 14beta2 and REL_14_STABLE versions.
So, I take a deep research on heap_update and RelationGetBufferForTuple
functions and find one code path for missing recheck of all-visible flag after
locking buffer with BUFFER_LOCK_EXCLUSIVE.

The following is the code path:
(1) heap_update calls RelationGetBufferForTuple to get new suitable buffer;
(2) during 'loop' loop of RelationGetBufferForTuple, it looks up one suitable new
buffer via FSM. But we assume that it was failed to find one available buffer here
and old buffer ('otherBuffer') was not set the all-visible flag.
(3) Next, it decides to bulk-extend the relation via RelationAddExtraBlocks and

get one new locked empty buffer via ReadBufferBI within ExclusiveLock.

(4) Then, it's succeed to ConditionalLockBuffer old buffer ('otherBuffer') and

returns the new buffer number without rechecking the all-visibility flag of old buffer.
(5) Finally, heap_update do the real update work and clear the all-visibility flag of
both old buffer and new buffer. It finds that the old buffer was set all-visibility
flag but vmbuffer is still 0. At last, visibilitymap_clear reports error 'wrong buffer
passed to visibilitymap_clear'.

I propose one patch which rechecks the all-visibility flag of old buffer after
ConditionalLockBuffer old buffer is successful. I start to test this patch for
couple of days and it seems to work well for me till now.

--
Regards,
rogers.ww

Attachment Content-Type Size
fix_missed_visibility_map_pin_for_old_buffer_after_extend.patch application/octet-stream 896 bytes

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Smith 2022-07-26 09:56:07 Re: Perform streaming logical transactions by background workers and parallel apply
Previous Message Simon Riggs 2022-07-26 09:34:09 Max compact as an FSM strategy