You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by mi...@apache.org on 2011/06/22 20:19:59 UTC

svn commit: r1138570 - in /db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access: btree/BTreeController.java heap/HeapCompressScan.java heap/HeapPostCommit.java

Author: mikem
Date: Wed Jun 22 18:19:58 2011
New Revision: 1138570

URL: http://svn.apache.org/viewvc?rev=1138570&view=rev
Log:
DERBY-5284 A derby crash at exactly right time during a btree split can cause a
corrupt db which can not be booted.

backport fix from trunk to 10.8 branch.

Fixed a problem during BTREE split.  The first phase of btree split sees
if it can reclaim space from committed deleted rows.  If it finds any
it purges these rows in a nested internal transaction.  It needs to hold
the latch on the page until end of transaction, but did not.  This allowed
a very small window of a few instructions where another insert could use
the space on the page and then a system crash could cause the purges to undo
but fail due to the insert.

The fix was to hold the latch and let commit release it.



Modified:
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java?rev=1138570&r1=1138569&r2=1138570&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java Wed Jun 22 18:19:58 2011
@@ -109,7 +109,11 @@ public class BTreeController extends Ope
      * it would be a waste to merge the page only to split it again to allow
      * the insert of the row causing the split.
      *
-	 * @return true if at least one row was purged.
+	 * @return true if at least one row was purged.  If true, then the routine
+     *              will leave the page latched, and the caller will release
+     *              the latch by committing or aborting the transaction.  The
+     *              latch must be held to end transaction to insure space on
+     *              the page remains available for a undo of the purge.
      *
      * @param open_btree The already open btree to use to get latch on page.
      * @param pageno     The page number of the leaf to attempt the reclaim on.
@@ -187,14 +191,23 @@ public class BTreeController extends Ope
         }
         finally
         {
-            if (controlRow != null) {
-                if (purged_at_least_one_row) {
+            if (controlRow != null) 
+            {
+                if (purged_at_least_one_row) 
+                {
                     // Set a hint in the page that scans positioned on it
                     // need to reposition because rows have disappeared from
-                    // the page.
+                    // the page.  If at least one row has been purged, then
+                    // do not release the latch.  Purge requires latch to 
+                    // be held until commit, where it will be released after
+                    // the commit log record has been logged.
                     controlRow.page.setRepositionNeeded();
                 }
-                controlRow.release();
+                else
+                {
+                    // Ok to release latch if no purging has happened.
+                    controlRow.release();
+                }
             }
         }
 
@@ -308,6 +321,12 @@ public class BTreeController extends Ope
                 // don't split if we reclaim any rows.
                 do_split = !reclaim_deleted_rows(split_open_btree, leaf_pageno);
 
+                // on return if !do_split then the latch on leaf_pageno is held
+                // and will be released by the committing or aborting the 
+                // transaction.  If a purge has been done, no other action on
+                // the page should be attempted (ie. a split) before committing
+                // the purges.
+
                 split_open_btree.close();
             }
         }
@@ -315,6 +334,9 @@ public class BTreeController extends Ope
         long new_leaf_pageno = leaf_pageno; 
         if (do_split)
         {
+            // no space was reclaimed from deleted rows, so do split to allow
+            // space for a subsequent insert.
+
             split_open_btree = new OpenBTree();
             split_open_btree.init(
                 this.init_open_user_scans, 

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java?rev=1138570&r1=1138569&r2=1138570&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java Wed Jun 22 18:19:58 2011
@@ -208,7 +208,11 @@ class HeapCompressScan 
                     // At this point assume table level lock, and that this
                     // transcation did not delete the row, so any
                     // deleted row must be a committed deleted row which can
-                    // be purged.
+                    // be purged.  Usually latches on purged pages must
+                    // be held until end transaction to prevent other 
+                    // transactions from using space necessary for a possible
+                    // undo of the purge, but in this case a table level
+                    // lock is held and will insure correct undo behavior.
                     scan_position.current_page.purgeAtSlot(
                         scan_position.current_slot, 1, false);
 

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java?rev=1138570&r1=1138569&r2=1138570&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java Wed Jun 22 18:19:58 2011
@@ -222,7 +222,10 @@ class HeapPostCommit implements Servicea
             {
                 // If no purge happened on the page and the page is not
                 // removed, feel free to unlatch it.  Otherwise, let
-                // transaction commit take care of it.
+                // transaction commit take care of it.  The latch must be
+                // held until end transaction in order to insure no other
+                // transaction uses the space freed by the purge, which
+                // would cause a subquent undo of the purge to fail.
 				if (!purgingDone)
                 {
                     page.unlatch();