> On Mar 31, 2021, at 10:31 AM, Mark Dilger <mark.dil...@enterprisedb.com> 
> wrote:
> 
> 
> 
>> On Mar 31, 2021, at 10:11 AM, Robert Haas <robertmh...@gmail.com> wrote:
>> 
>> On Wed, Mar 31, 2021 at 12:34 AM Mark Dilger
>> <mark.dil...@enterprisedb.com> wrote:
>>> I'm not looking at the old VACUUM FULL code, but my assumption is that if 
>>> the xvac code were resurrected, then when a tuple is moved off by a VACUUM 
>>> FULL, the old tuple and associated toast cannot be pruned until concurrent 
>>> transactions end.  So, if amcheck is running more-or-less concurrently with 
>>> the VACUUM FULL and has a snapshot xmin no newer than the xid of the VACUUM 
>>> FULL's xid, it can check the toast associated with the moved off tuple 
>>> after the VACUUM FULL commits.  If instead the VACUUM FULL xid was older 
>>> than amcheck's xmin, then the toast is in danger of being vacuumed away.  
>>> So the logic in verify_heapam would need to change to think about this 
>>> distinction.  We don't have to concern ourselves about that, because VACUUM 
>>> FULL cannot be running, and so the xid for it must be older than our xmin, 
>>> and hence the toast is unconditionally not safe to check.
>>> 
>>> I'm changing the comments back to how you had them, but I'd like to know 
>>> why my reasoning is wrong.
>> 
>> Let's start by figuring out *whether* your reasoning is wrong. My
>> assumption was that old-style VACUUM FULL would move tuples without
>> retoasting. That is, if we decided to move a tuple from page 2 of the
>> main table to page 1, we would just write the tuple into page 1,
>> marking it moved-in, and on page 2 we would mark it moved-off. And
>> that we would not examine or follow any TOAST pointers at all, so
>> whatever TOAST entries existed would be shared between the two tuples.
>> One tuple or the other would eventually die, depending on whether xvac
>> went on to commit or abort, but either way the TOAST doesn't need
>> updating because there's always exactly 1 remaining tuple using
>> pointers to those TOAST values.
>> 
>> Your assumption seems to be the opposite, that the TOASTed values
>> would be retoasted as part of VF. If that is true, then your idea is
>> right.
>> 
>> Do you agree with this analysis? If so, we can check the code and find
>> out which way it actually worked.
> 
> Actually, that makes a lot of sense without even looking at the old code.  I 
> was implicitly assuming that the toast table was undergoing a VF also, and 
> that the toast pointers in the main table tuples would be updated to point to 
> the new location, so we'd be unable to follow the pointers to the old 
> location without danger of the old location entries being vacuumed away. But 
> if the main table tuples get moved while keeping their toast pointers 
> unaltered, then you don't have to worry about that, although you do have to 
> worry that a VF of the main table doesn't help so much with toast table bloat.
> 
> We're only discussing this in order to craft the right comment for a bit of 
> code with respect to a hypothetical situation in which VF gets resurrected, 
> so I'm not sure this should be top priority, but I'm curious enough now to go 
> read the old code....

Well, that's annoying.  The documentation of postgres 8.2 for vacuum full [1] 
says,

  Selects "full" vacuum, which may reclaim more space, but takes much longer 
and exclusively locks the table.

I read "exclusively locks" as meaning it takes an ExclusiveLock, but the code 
shows that it takes an AccessExclusiveLock.  I think the docs are pretty 
misleading here, though I understand that grammatically it is hard to say 
"accessively exclusively locks" or such.  But a part of my analysis was based 
on the reasoning that if VF only takes an ExclusiveLock, then there must be 
concurrent readers possible.  VF went away long enough ago that I had forgotten 
exactly how inconvenient it was.

[1] https://www.postgresql.org/docs/8.2/sql-vacuum.html

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company





Reply via email to