Re: Summary and Plan for Hot Standby

Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>

From: Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>
To: Simon Riggs <simon@2ndQuadrant.com>
Cc: pgsql-hackers@postgresql.org
Date: 2009-11-15T18:30:39Z
Lists: pgsql-hackers
Simon Riggs wrote:
> On Sun, 2009-11-15 at 19:36 +0200, Heikki Linnakangas wrote:
>> Simon Riggs wrote:
>>> On Sun, 2009-11-15 at 16:07 +0200, Heikki Linnakangas wrote:
>>>
>>>> The assumption that b-tree vacuum records don't need conflict
>>>> resolution because we did that with the additional cleanup-info record
>>>> works ATM, but it hinges on the fact that we don't delete any tuples
>>>> marked as killed while we do the vacuum. 
>>>> That seems like a low-hanging
>>>> fruit that I'd actually like to do now that I spotted it, but will
>>>> then need to fix b-tree vacuum records accordingly. We'd probably need
>>>> to do something about the previous item first to keep performance
>>>> acceptable.
>>> We can optimise that by using the xlog pointer of the HeapInfo record.
>>> Any blocks cleaned that haven't been further updated can avoid
>>> generating further btree deletion records.
>> Sorry, I don't understand that. (Remember that marking index tuples as
>> killed is not WAL-logged.)
> 
> Remember that blocks are marked with an LSN? When we insert a WAL record
> it has an LSN also. So we can tell which btree blocks might have had
> been written to after the HeapInfo record is generated. So if a block
> hasn't been recently updated or it doesn't have any killed tuples then
> we need not generate a record to handle a possible conflict.

Hmm, perhaps we're talking about the same thing. What I'm seeing is that
we could easily do this:

*** a/src/backend/access/nbtree/nbtree.c
--- b/src/backend/access/nbtree/nbtree.c
***************
*** 843,855 **** restart:
  				 offnum <= maxoff;
  				 offnum = OffsetNumberNext(offnum))
  			{
  				IndexTuple	itup;
  				ItemPointer htup;

! 				itup = (IndexTuple) PageGetItem(page,
! 												PageGetItemId(page, offnum));
  				htup = &(itup->t_tid);
! 				if (callback(htup, callback_state))
  					deletable[ndeletable++] = offnum;
  			}
  		}
--- 843,856 ----
  				 offnum <= maxoff;
  				 offnum = OffsetNumberNext(offnum))
  			{
+ 				ItemId		itemid;
  				IndexTuple	itup;
  				ItemPointer htup;

! 				itemid = PageGetItemId(page, offnum);
! 				itup = (IndexTuple) PageGetItem(page, itemid);
  				htup = &(itup->t_tid);
! 				if (callback(htup, callback_state) || ItemIdIsDead(itemid))
  					deletable[ndeletable++] = offnum;
  			}
  		}

But if we do that, b-tree vacuum records are going to need conflict
resolution, just like the b-tree non-vacuum deletion records. The LSN
doesn't help there, because when an itemid is marked as dead, the LSN is
not updated.

-- 
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com