MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:October 16 2009 3:37pm
Subject:bzr commit into mysql-5.1-telco-6.2 branch (frazer:3019) Bug#48113
View as plain text  
#At file:///home/frazer/bzr/mysql-5.1-telco-6.2/

 3019 Frazer Clement	2009-10-16
      Bug#48113 : Ndb : Insert hitting DD space exhaustion does not lock following tuple ops
      modified:
        storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
        storage/ndb/test/ndbapi/testBasic.cpp
        storage/ndb/test/run-test/daily-basic-tests.txt

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2009-10-16 15:37:14 +0000
@@ -1342,6 +1342,7 @@ int Dbtup::handleInsertReq(Signal* signa
                      regTabPtr->m_attributes[MM].m_no_of_dynamic);
   bool varalloc = vardynsize || regTabPtr->m_bits & Tablerec::TR_ForceVarPart;
   bool rowid = req_struct->m_use_rowid;
+  bool update_acc = false; 
   Uint32 real_page_id = regOperPtr.p->m_tuple_location.m_page_no;
   Uint32 frag_page_id = req_struct->frag_page_id;
 
@@ -1543,17 +1544,12 @@ int Dbtup::handleInsertReq(Signal* signa
       }
     }
     real_page_id = regOperPtr.p->m_tuple_location.m_page_no;
-    regOperPtr.p->m_tuple_location.m_page_no= frag_page_id;
-    c_lqh->accminupdate(signal,
-			regOperPtr.p->userpointer,
-			&regOperPtr.p->m_tuple_location);
+    update_acc = true; /* Will be updated later once success is known */
     
     base = (Tuple_header*)ptr;
     base->m_operation_ptr_i= regOperPtr.i;
     base->m_header_bits= Tuple_header::ALLOC |
       (vardynsize ? Tuple_header::VAR_PART : 0);
-
-    regOperPtr.p->m_tuple_location.m_page_no = real_page_id;
   }
   else 
   {
@@ -1610,6 +1606,25 @@ int Dbtup::handleInsertReq(Signal* signa
     disk_ptr->m_header_bits = 0;
     disk_ptr->m_base_record_ref= ref.ref();
   }
+
+  /* Have been successful with disk + mem, update ACC to point to
+   * new record if necessary
+   * Failures in disk alloc will skip this part
+   */
+  if (update_acc)
+  {
+    /* Acc stores the local key with the frag_page_id rather
+     * than the real_page_id
+     */
+    ndbassert(regOperPtr.p->m_tuple_location.m_page_no == real_page_id);
+
+    Local_key accKey = regOperPtr.p->m_tuple_location;
+    accKey.m_page_no = frag_page_id;
+
+    c_lqh->accminupdate(signal,
+                        regOperPtr.p->userpointer,
+                        &accKey);
+  }
   
   if (regTabPtr->m_bits & Tablerec::TR_Checksum) 
   {

=== modified file 'storage/ndb/test/ndbapi/testBasic.cpp'
--- a/storage/ndb/test/ndbapi/testBasic.cpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/test/ndbapi/testBasic.cpp	2009-10-16 15:37:14 +0000
@@ -1526,6 +1526,71 @@ runBug20535(NDBT_Context* ctx, NDBT_Step
     return NDBT_FAILED;
 }
 
+
+int
+runDDInsertFailUpdateBatch(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbRestarter restarter;
+  
+  const NdbDictionary::Table * tab = ctx->getTab();
+  
+  {
+    bool tabHasDD = false;
+    
+    for(int i = 0; i<tab->getNoOfColumns(); i++)
+    {
+      tabHasDD |= (tab->getColumn(i)->getStorageType() == 
+                   NdbDictionary::Column::StorageTypeDisk);
+    }
+    
+    if (!tabHasDD)
+    {
+      ndbout_c("Table %s has no disk attributes, skipping",
+               tab->getName());
+      return NDBT_OK;
+    }
+  }
+
+  HugoOperations hugoOps(*ctx->getTab());
+  Ndb* pNdb = GETNDB(step);
+
+  /* Error Insert 4021 - DD tuple insert will fail in disk
+   * space preallocation step
+   */
+  restarter.insertErrorInAllNodes(4021);
+
+  int result = NDBT_OK;
+  
+  for (Uint32 loop = 0; loop < 100; loop ++)
+  {
+    CHECK(hugoOps.startTransaction(pNdb) == 0);
+    
+    /* Create batch with insert op (which will fail due to disk allocation issue)
+     * followed by update op on same pk
+     * Transaction will abort due to insert failure, and reason should be
+     * disk space exhaustion, not any issue with the update.
+     */
+    CHECK(hugoOps.pkInsertRecord(pNdb, loop, 1, 0) == 0);
+    
+    /* Add up to 16 updates after the insert */
+    Uint32 numUpdates = 1 + (loop % 15);
+    for (Uint32 updateCnt = 0; updateCnt < numUpdates; updateCnt++)
+      CHECK(hugoOps.pkUpdateRecord(pNdb, loop, 1, 1+updateCnt) == 0);
+    
+    CHECK(hugoOps.execute_Commit(pNdb) != 0); /* Expect failure */
+    
+    NdbError err= hugoOps.getTransaction()->getNdbError();
+    
+    CHECK(err.code == 1601); // Disk prealloc error
+    
+    hugoOps.closeTransaction(pNdb);
+  }  
+
+  restarter.insertErrorInAllNodes(0);
+  
+  return result;
+}
+
 template class Vector<NdbRecAttr*>;
 
 NDBT_TESTSUITE(testBasic);
@@ -1823,6 +1888,10 @@ TESTCASE("Bug20535", 
 	 "Verify what happens when we fill the db" ){
   STEP(runBug20535);
 }
+TESTCASE("DDInsertFailUpdateBatch",
+         "Verify DD insert failure effect on other ops in batch on same PK"){
+  STEP(runDDInsertFailUpdateBatch);
+}
 NDBT_TESTSUITE_END(testBasic);
 
 #if 0

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2009-10-12 11:47:31 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2009-10-16 15:37:14 +0000
@@ -1366,3 +1366,7 @@ max-time: 300
 cmd: testNdbApi
 args: -n ReadColumnDuplicates
 
+max-time: 300
+cmd: testBasic
+args: -n DDInsertFailUpdateBatch D1 D2
+

Thread
bzr commit into mysql-5.1-telco-6.2 branch (frazer:3019) Bug#48113Frazer Clement16 Oct