Hi,
On 2021-05-06 21:40:18 +0900, Masahiko Sawada wrote:
> Since we set all_visible_according_to_vm before acquiring the buffer
> lock it's likely to happen that the page gets modified and all-visible
> bit is cleared after setting true to all_visible_according_to_vm. This
> assertion can easily be reproduced by adding a delay before the buffer
> lock and invoking autovacuums frequently:
> So we should recheck also visibility map bit there but I think we can
> remove this assertion since we already do that in later code and we
> don’t treat this case as a should-not-happen case:
>
> /*
> * As of PostgreSQL 9.2, the visibility map bit should never be set if
> * the page-level bit is clear. However, it's possible that the bit
> * got cleared after we checked it and before we took the buffer
> * content lock, so we must recheck before jumping to the conclusion
> * that something bad has happened.
> */
> else if (all_visible_according_to_vm && !PageIsAllVisible(page)
> && VM_ALL_VISIBLE(vacrel->rel, blkno, &vmbuffer))
> {
> elog(WARNING, "page is not marked all-visible but
> visibility map bit is set in relation \"%s\" page %u",
> vacrel->relname, blkno);
> visibilitymap_clear(vacrel->rel, blkno, vmbuffer,
> VISIBILITYMAP_VALID_BITS);
> }
>
> I've attached a patch removing the assertion.
I think it'd be a good idea to audit the other uses of
all_visible_according_to_vm to make sure there's no issues there. Can't
this e.g. make us miss setting all-visible in
/*
* Handle setting visibility map bit based on what the VM said about
* the page before pruning started, and using prunestate
*/
if (!all_visible_according_to_vm && prunestate.all_visible)
Perhaps we should update all_visible_according_to_vm after locking the
buffer, if PageIsAllVisible(page) is true?
Greetings,
Andres Freund