List:Commits« Previous MessageNext Message »
From:Kevin Lewis Date:September 30 2008 6:17pm
Subject:bzr commit into mysql-6.0-falcon-team branch (klewis:2843) Bug#39321
View as plain text  
#At file:///C:/Work/bzr/Merge/mysql-6.0-falcon-team/

 2843 Kevin Lewis	2008-09-30
      Bug#39321 Add an exclusive lock on Database::syncScavenge in
      Database::truncateTable before the lock of Table::syncObject
      just in case the truncateTable process has to call
      Database::forceRecordScavenge.  syncScavenge must be locked
      before Table::syncObject because the scavenger does it that way.
      
      According to the Deadlock Predictor (SyncHandler.cpp), 
      syncScavenge must also be locked before Database::syncTables.
modified:
  storage/falcon/Database.cpp

=== modified file 'storage/falcon/Database.cpp'
--- a/storage/falcon/Database.cpp	2008-09-11 10:56:00 +0000
+++ b/storage/falcon/Database.cpp	2008-09-30 18:17:19 +0000
@@ -686,7 +686,6 @@ void Database::createDatabase(const char
 		deleteFilesOnExit = true;
 		throw;
 		}
-
 }
 
 void Database::openDatabase(const char * filename)
@@ -1455,50 +1454,61 @@ void Database::dropTable(Table *table, T
 
 void Database::truncateTable(Table *table, Sequence *sequence, Transaction *transaction)
 {
-	Sync syncDDL(&syncSysDDL, "Database::truncateTable(1)");
-	syncDDL.lock(Exclusive);
-	
-	table->checkDrop();
-	
 	// Check for records in active transactions
 
 	if (hasUncommittedRecords(table, transaction))
 		throw SQLError(UNCOMMITTED_UPDATES, "table %s.%s has uncommitted updates and cannot be truncated",
 						table->schemaName, table->name);
-						   
-	// Block table drop/add, table list scans ok
-	
-	Sync syncTbl(&syncTables, "Database::truncateTable(2)");
-	syncTbl.lock(Shared);
+
+	// Lock SystemDDL first.  This lock can happen multiple times in many call stacks,
+	// both before and after the following locks.  So it is important that we get an 
+	// exclusive lock first.
+
+	Sync syncDDLLock(&syncSysDDL, "Database::truncateTable(SysDDL)");
+	syncDDLLock.lock(Exclusive);
+	
+	// Lock syncScavenge before locking syncSysDDL, syncTables, or table->syncObject.
+	// The scavenger locks syncScavenge  and then syncTables
+	// If we run out of record memory, forceRecordScavenge will eventually call table->syncObject.
+
+	Sync syncScavengeLock(&syncScavenge, "Database::truncateTable(scavenge)");
+	syncScavengeLock.lock(Exclusive);
+
+	table->checkDrop();
 	
+	// Block table drop/add, table list scans ok
+
+	Sync syncTablesLock(&syncTables, "Database::truncateTable(tables)");
+	syncTablesLock.lock(Shared);
+
 	//Lock sections (factored out of SRLDropTable to avoid a deadlock)
 	//The lock order (serialLog->syncSections before table->syncObject) is 
 	//important
 
-	Sync syncSections(&serialLog->syncSections, "Database::truncateTable(3)");
-	syncSections.lock(Exclusive);
-	
+	Sync syncSectionsLock(&serialLog->syncSections, "Database::truncateTable(sections)");
+	syncSectionsLock.lock(Exclusive);
+
 	// No table access until truncate completes
-	
-	Sync syncObj(&table->syncObject, "Database::truncateTable(4)");
-	syncObj.lock(Exclusive);
-	
+
+	Sync syncTableLock(&table->syncObject, "Database::truncateTable(table)");
+	syncTableLock.lock(Exclusive);
+
 	table->deleting = true;
-	
+
 	// Purge records out of committed transactions
-	
+
 	transactionManager->truncateTable(table, transaction);
-	
+
 	Transaction *sysTransaction = getSystemTransaction();
-	
+
 	// Recreate data/blob sections and indexes
-	
+
 	table->truncate(sysTransaction);
-	
+
 	commitSystemTransaction();
-	
+
 	// Delete and recreate the sequence
-	
+
 	if (sequence)
 		sequence = sequence->recreate();
 }

Thread
bzr commit into mysql-6.0-falcon-team branch (klewis:2843) Bug#39321Kevin Lewis30 Sep