Attached is a patch to remove the lock protection for
HeapTupleSatisfiesVacuum() in index code. The basic idea is: if we can do
a pin/lock/unlock sequence on a page, then without locking again, we are
gauranteed that there is no vacuum process acting on the same page.
According to buffer pool access rule #4, we then can examine/change the
hints bit safely.

Regards,
Qingqing
Index: indexam.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/index/indexam.c,v
retrieving revision 1.93
diff -c -r1.93 indexam.c
*** indexam.c   7 May 2006 01:21:30 -0000       1.93
--- indexam.c   6 Jun 2006 01:53:41 -0000
***************
*** 503,517 ****
                 * to not return it on future indexscans.
                 *
                 * We told heap_release_fetch to keep a pin on the buffer, so 
we can
!                * re-access the tuple here.  But we must re-lock the buffer 
first.
                 */
-               LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE);
- 
                if (HeapTupleSatisfiesVacuum(heapTuple->t_data, 
RecentGlobalXmin,
                                                                         
scan->xs_cbuf) == HEAPTUPLE_DEAD)
                        scan->kill_prior_tuple = true;
- 
-               LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
        }
  
        /* Success exit */
--- 503,513 ----
                 * to not return it on future indexscans.
                 *
                 * We told heap_release_fetch to keep a pin on the buffer, so 
we can
!                * re-access the tuple here without re-lock the buffer.
                 */
                if (HeapTupleSatisfiesVacuum(heapTuple->t_data, 
RecentGlobalXmin,
                                                                         
scan->xs_cbuf) == HEAPTUPLE_DEAD)
                        scan->kill_prior_tuple = true;
        }
  
        /* Success exit */
Index: nbtinsert.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v
retrieving revision 1.137
diff -c -r1.137 nbtinsert.c
*** nbtinsert.c 8 May 2006 00:00:09 -0000       1.137
--- nbtinsert.c 6 Jun 2006 01:54:55 -0000
***************
*** 255,261 ****
                                         * killed.      This logic should match 
index_getnext and
                                         * btgettuple.
                                         */
-                                       LockBuffer(hbuffer, BUFFER_LOCK_SHARE);
                                        if 
(HeapTupleSatisfiesVacuum(htup.t_data, RecentGlobalXmin,
                                                                                
                 hbuffer) == HEAPTUPLE_DEAD)
                                        {
--- 255,260 ----
***************
*** 265,271 ****
                                                else
                                                        
SetBufferCommitInfoNeedsSave(buf);
                                        }
-                                       LockBuffer(hbuffer, BUFFER_LOCK_UNLOCK);
                                }
                                ReleaseBuffer(hbuffer);
                        }
--- 264,269 ----
Index: bufmgr.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v
retrieving revision 1.207
diff -c -r1.207 bufmgr.c
*** bufmgr.c    14 Apr 2006 03:38:55 -0000      1.207
--- bufmgr.c    6 Jun 2006 02:07:09 -0000
***************
*** 1686,1693 ****
        bufHdr = &BufferDescriptors[buffer - 1];
  
        Assert(PrivateRefCount[buffer - 1] > 0);
-       /* here, either share or exclusive lock is OK */
-       Assert(LWLockHeldByMe(bufHdr->content_lock));
  
        /*
         * This routine might get called many times on the same page, if we are
--- 1686,1691 ----
Index: README
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/buffer/README,v
retrieving revision 1.9
diff -c -r1.9 README
*** README      31 Mar 2006 23:32:06 -0000      1.9
--- README      6 Jun 2006 02:22:25 -0000
***************
*** 64,70 ****
  manage to be a conflict it would merely mean that one bit-update would
  be lost and need to be done again later.  These four bits are only hints
  (they cache the results of transaction status lookups in pg_clog), so no
! great harm is done if they get reset to zero by conflicting updates.
  
  5. To physically remove a tuple or compact free space on a page, one
  must hold a pin and an exclusive lock, *and* observe while holding the
--- 64,73 ----
  manage to be a conflict it would merely mean that one bit-update would
  be lost and need to be done again later.  These four bits are only hints
  (they cache the results of transaction status lookups in pg_clog), so no
! great harm is done if they get reset to zero by conflicting updates. If
! you can guarantee there is no vacuum process (see rule #5) on the page,
! then it is safe to just hold the pin and do the changes. In practice, a 
! pin/lock/unlock sequence can make sure of that.
  
  5. To physically remove a tuple or compact free space on a page, one
  must hold a pin and an exclusive lock, *and* observe while holding the
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to