Justify nbtree page split locking in code comment.
authorPeter Geoghegan <[email protected]>
Fri, 27 Mar 2020 23:44:52 +0000 (16:44 -0700)
committerPeter Geoghegan <[email protected]>
Fri, 27 Mar 2020 23:44:52 +0000 (16:44 -0700)
Delaying unlocking the right child page until after the point that the
left child's parent page has been refound is no longer truly necessary.
Commit 40dae7ec made nbtree tolerant of interrupted page splits.  VACUUM
was taught to avoid deleting a page that happens to be the right half of
an incomplete split.  As long as page splits don't unlock the left child
page until the end of the second/final phase, it should be safe to
unlock the right child page earlier (at the end of the first phase).

It probably isn't actually useful to release the right child's lock
earlier like this (it probably won't improve performance).  Even still,
pointing out that it ought to be safe to do so should make it easier to
understand the overall design.

src/backend/access/nbtree/nbtinsert.c

index 00df0e1b88fbb51d03ee98fec48d629a082349d2..1675298f73dea3748b1325ae958aff42e7c3c33f 100644 (file)
@@ -2128,8 +2128,17 @@ _bt_insert_parent(Relation rel,
                pbuf = _bt_getstackbuf(rel, stack, bknum);
 
                /*
-                * Now we can unlock the right child. The left child will be unlocked
-                * by _bt_insertonpg().
+                * Unlock the right child.  The left child will be unlocked in
+                * _bt_insertonpg().
+                *
+                * Unlocking the right child must be delayed until here to ensure that
+                * no concurrent VACUUM operation can become confused.  Page deletion
+                * cannot be allowed to fail to re-find a downlink for the rbuf page.
+                * (Actually, this is just a vestige of how things used to work.  The
+                * page deletion code is expected to check for the INCOMPLETE_SPLIT
+                * flag on the left child.  It won't attempt deletion of the right
+                * child until the split is complete.  Despite all this, we opt to
+                * conservatively delay unlocking the right child until here.)
                 */
                _bt_relbuf(rel, rbuf);