#At file:///home/cpowers/work/dev/dev-04/mysql/
2970 Christopher Powers 2009-01-22
Bug #39678 Assertion (bdb) fails in IndexRootPage::indexMerge during recovery
Improved synchronization between concurrent DROP INDEX and INSERT/UPDATE operations
on the same table.
modified:
storage/falcon/Index.cpp
storage/falcon/SRLUpdateIndex.cpp
storage/falcon/SerialLog.cpp
storage/falcon/Table.cpp
per-file messages:
storage/falcon/Index.cpp
Index::deleteIndex()
- Set indexId == -1 before writing SRLDeleteIndex to the serial log.
storage/falcon/SRLUpdateIndex.cpp
SRLUpdateIndex::append()
- Check indexId == -1 inside of the syncIndexes lock
- Ignore DeferredIndexes with indexId == -1
storage/falcon/SerialLog.cpp
Added recovery progress log messages
storage/falcon/Table.cpp
Table::insertIndexes()
- Protect Index::insert() from concurrent DDL
=== modified file 'storage/falcon/Index.cpp'
--- a/storage/falcon/Index.cpp 2009-01-15 20:29:54 +0000
+++ b/storage/falcon/Index.cpp 2009-01-22 18:40:02 +0000
@@ -406,8 +406,14 @@ void Index::deleteIndex(Transaction *tra
{
if (!damaged && indexId != -1)
{
- dbb->deleteIndex(indexId, indexVersion, TRANSACTION_ID(transaction));
+
+ // The Index class does not use a Sync object. To ensure that concurrent
+ // SRLUpdateIndex operations ignore DeferredIndexes associated with
+ // this index, set indexId to -1 before writing to the Serial Log.
+
+ int id = indexId;
indexId = -1;
+ dbb->deleteIndex(id, indexVersion, TRANSACTION_ID(transaction));
}
}
=== modified file 'storage/falcon/SRLUpdateIndex.cpp'
--- a/storage/falcon/SRLUpdateIndex.cpp 2008-11-14 15:38:44 +0000
+++ b/storage/falcon/SRLUpdateIndex.cpp 2009-01-22 18:40:02 +0000
@@ -40,21 +40,28 @@ SRLUpdateIndex::~SRLUpdateIndex(void)
void SRLUpdateIndex::append(DeferredIndex* deferredIndex)
{
+ // To ensure coordination with a concurrent SRLDeleteIndex, grab syncIndexes
+ // before getting the index id from the DeferredIndex.
+
+ Sync syncIndexes(&log->syncIndexes, "SRLUpdateIndex::append(Indexes)");
+ syncIndexes.lock(Shared);
+
Sync syncDI(&deferredIndex->syncObject, "SRLUpdateIndex::append(DI)");
syncDI.lock(Shared);
- if (!deferredIndex->index)
- return;
+ Index* index = deferredIndex->index;
- uint indexId = deferredIndex->index->indexId;
- int idxVersion = deferredIndex->index->indexVersion;
- int tableSpaceId = deferredIndex->index->dbb->tableSpaceId;
+ // A null index or indexId == -1 means that the index has been deleted
+
+ if (!index || index->indexId == -1)
+ return;
+
+ int idxId = index->indexId;
+ int idxVersion = index->indexVersion;
+ int tableSpaceId = index->dbb->tableSpaceId;
syncDI.unlock();
- Sync syncIndexes(&log->syncIndexes, "SRLUpdateIndex::append(Indexes)");
- syncIndexes.lock(Shared);
-
Transaction *transaction = deferredIndex->transaction;
DeferredIndexWalker walker(deferredIndex, NULL);
uint64 virtualOffset = 0;
@@ -70,7 +77,7 @@ void SRLUpdateIndex::append(DeferredInde
if (virtualOffset == 0)
virtualOffset = log->startRecordVirtualOffset;
- log->updateIndexUseVector(indexId, tableSpaceId, 1);
+ log->updateIndexUseVector(idxId, tableSpaceId, 1);
SerialLogTransaction *srlTrans = log->getTransaction(transaction->transactionId);
srlTrans->setTransaction(transaction);
ASSERT(transaction->writePending);
@@ -79,7 +86,7 @@ void SRLUpdateIndex::append(DeferredInde
putInt(tableSpaceId);
putInt(transaction->transactionId);
- putInt(indexId);
+ putInt(idxId);
putInt(idxVersion);
// Initialize the length field, adjust with correct length later.
@@ -105,7 +112,7 @@ void SRLUpdateIndex::append(DeferredInde
}
int len = (int) (log->writePtr - start);
- //printf("SRLUpdateIndex::append tid %d, index %d, length %d, ptr %x (%x)\n", transaction->transactionId, indexId, len, lengthPtr, org);
+ //printf("SRLUpdateIndex::append tid %d, index %d, length %d, ptr %x (%x)\n", transaction->transactionId, idxId, len, lengthPtr, org);
ASSERT(len >= 0);
// Update the length field
=== modified file 'storage/falcon/SerialLog.cpp'
--- a/storage/falcon/SerialLog.cpp 2008-11-20 17:05:50 +0000
+++ b/storage/falcon/SerialLog.cpp 2009-01-22 18:40:02 +0000
@@ -51,6 +51,7 @@ static const char THIS_FILE[]=__FILE__;
#endif
static const int TRACE_PAGE = 0;
+static const int RECORD_MAX = 100000;
extern uint falcon_gopher_threads;
extern uint64 falcon_serial_log_file_size;
@@ -284,9 +285,9 @@ void SerialLog::recover()
SerialLogBlock *recoveryBlock = recoveryWindow->firstBlock();
recoveryBlockNumber = recoveryBlock->blockNumber;
SerialLogBlock *lastBlock = findLastBlock(recoveryWindow);
- Log::log("first recovery block is " I64FORMAT "\n",
+ Log::log("/nFirst recovery block is " I64FORMAT "\n",
(otherWindow) ? otherWindow->firstBlock()->blockNumber : recoveryBlockNumber);
- Log::log("last recovery block is " I64FORMAT "\n", lastBlock->blockNumber);
+ Log::log("Last recovery block is " I64FORMAT "\n", lastBlock->blockNumber);
if (otherWindow)
{
@@ -306,7 +307,7 @@ void SerialLog::recover()
if (readBlockNumber == 0)
readBlockNumber = lastBlock->blockNumber;
- Log::log("recovery read block is " I64FORMAT "\n", readBlockNumber);
+ Log::log("Recovery read block is " I64FORMAT "\n", readBlockNumber);
nextBlockNumber = lastBlock->blockNumber + 1;
lastWindow->deactivateWindow();
SerialLogWindow *window = findWindowGivenBlock(readBlockNumber);
@@ -328,11 +329,20 @@ void SerialLog::recover()
recoveryIndexes = new RecoveryObjects(this);
recoveryPhase = 1; // Take Inventory (serialLogTransactions, recoveryObject states, last checkpoint)
- // Make a first pass finding records, transactions, etc.
+ Log::log("Recovery phase 1...\n");
+
+ unsigned long int recordCount = 0;
while ( (record = control.nextRecord()) )
+ {
+ if (++recordCount % RECORD_MAX == 0)
+ Log::log("Processed: %8ld\n", recordCount);
+
record->pass1();
+ }
+ Log::log("Processed: %8ld\n", recordCount);
+
//control.debug = false;
pass1 = false;
control.setWindow(window, block, 0);
@@ -344,9 +354,19 @@ void SerialLog::recover()
// Next, make a second pass to reallocate any necessary pages
+ Log::log("\nRecovery phase 2...\n");
+ recordCount = 0;
+
while ( (record = control.nextRecord()) )
+ {
+ if (++recordCount % RECORD_MAX == 0)
+ Log::log("Processed: %8ld\n", recordCount);
+
if (!isTableSpaceDropped(record->tableSpaceId) || record->type == srlDropTableSpace)
record->pass2();
+ }
+
+ Log::log("Processed: %8ld\n", recordCount);
recoveryPages->reset();
recoveryIndexes->reset();
@@ -363,10 +383,19 @@ void SerialLog::recover()
// Make a third pass doing things
+ Log::log("\nRecovery phase 3...\n");
+ recordCount = 0;
+
while ( (record = control.nextRecord()) )
+ {
+ if (++recordCount % RECORD_MAX == 0)
+ Log::log("Processed: %8ld\n", recordCount);
+
if (!isTableSpaceDropped(record->tableSpaceId))
record->redo();
-
+ }
+
+ Log::log("Processed: %8ld\n", recordCount);
for (SerialLogTransaction *action, **ptr = &running.first; (action = *ptr);)
if (action->completedRecovery())
=== modified file 'storage/falcon/Table.cpp'
--- a/storage/falcon/Table.cpp 2009-01-17 08:51:59 +0000
+++ b/storage/falcon/Table.cpp 2009-01-22 18:40:02 +0000
@@ -1255,24 +1255,33 @@ void Table::insertIndexes(Transaction *t
{
if (indexes)
{
+ Sync syncTable(&syncObject, "Table::insertIndexes");
+
FOR_INDEXES(index, this);
- Sync sync(&index->syncUnique, "Table::insertIndexes");
+ Sync syncUnique(&index->syncUnique, "Table::insertIndexes");
if (needUniqueCheck(index,record))
for(;;)
{
- sync.lock(Exclusive);
+ syncUnique.lock(Exclusive);
- if(!checkUniqueIndex(index, transaction, record, &sync))
+ if(!checkUniqueIndex(index, transaction, record, &syncUnique))
break;
}
- index->insert(record, transaction);
+ // Block concurrent DDL with a shared lock. Double-check the
+ // index id in case the index was deleted.
+
+ syncTable.lock(Shared);
+
+ if (index->indexId != -1)
+ index->insert(record, transaction);
+
+ syncTable.unlock();
END_FOR;
}
}
-
void Table::update(Transaction * transaction, Record * oldRecord, int numberFields, Field** updateFields, Value * * values)
{
database->preUpdate();
| Thread |
|---|
| • bzr commit into mysql-6.0-falcon-team branch (christopher.powers:2970)Bug#39678 | Christopher Powers | 22 Jan |