]> granicus.if.org Git - postgresql/commitdiff
Avoid unnecessary page-level SSI lock check in heap_insert().
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 16 Sep 2011 18:47:20 +0000 (14:47 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 16 Sep 2011 18:47:20 +0000 (14:47 -0400)
As observed by Heikki, we need not conflict on heap page locks during an
insert; heap page locks are only aggregated tuple locks, they don't imply
locking "gaps" as index page locks do.  So we can avoid some unnecessary
conflicts, and also do the SSI check while not holding exclusive lock on
the target buffer.

Kevin Grittner, reviewed by Jeff Davis.  Back-patch to 9.1.

src/backend/access/heap/heapam.c

index 06db65d76f99b5cfad483fe03932ec17da9acfee..17950d482c196bccdc64ae01a7762e6a1fad4cde 100644 (file)
@@ -1916,6 +1916,18 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
        else
                heaptup = tup;
 
+       /*
+        * We're about to do the actual insert -- but check for conflict first,
+        * to avoid possibly having to roll back work we've just done.
+        *
+        * For a heap insert, we only need to check for table-level SSI locks.
+        * Our new tuple can't possibly conflict with existing tuple locks, and
+        * heap page locks are only consolidated versions of tuple locks; they do
+        * not lock "gaps" as index page locks do.  So we don't need to identify
+        * a buffer before making the call.
+        */
+       CheckForSerializableConflictIn(relation, NULL, InvalidBuffer);
+
        /*
         * Find buffer to insert this tuple into.  If the page is all visible,
         * this will also pin the requisite visibility map page.
@@ -1924,13 +1936,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
                                                                           InvalidBuffer, options, bistate,
                                                                           &vmbuffer, NULL);
 
-       /*
-        * We're about to do the actual insert -- check for conflict at the
-        * relation or buffer level first, to avoid possibly having to roll back
-        * work we've just done.
-        */
-       CheckForSerializableConflictIn(relation, NULL, buffer);
-
        /* NO EREPORT(ERROR) from here till changes are logged */
        START_CRIT_SECTION();