From: Kevin Lewis Date: January 17 2009 11:24pm Subject: Re: Table::checkUniqueRecordVersion() List-Archive: http://lists.mysql.com/falcon/390 Message-Id: <497268B2.8060700@sun.com> MIME-Version: 1.0 Content-Type: text/plain; format=flowed; charset=ISO-8859-1 Content-Transfer-Encoding: 7BIT Chris, recRollback could be on a record that was deleted and is now being rolled back. So at least this state is valid as well. What others??? recNoChill: This may be a possibility! This is a temporary state that could be repalacing recDeleted while it is added to the transaction. I surveyed the calls to Transaction::addRecord where this is set. Sometimes it occurs before the record shows up on the recordLeaf for others to see (Table::insert or validateAndInsert) before addRecord() is called. Sometimes it is the other way around. If we make it standard procedure to add new record versions to the transaction first, before inserting into the record tree, then we could be sure that no other thread will find it in checkUniqueRecordVersion() or duplicateKey(). recInserting: This is always a new record, so it should always haveData. recDeleting, Happens during ~RecordVersion(). That means the useCount is zero. recEndChain: It may be possible for a checkUniqueRecordVersion or duplicateKey() to be traversing a chain at the same time as a scavengeSavepoint(). But it looks like syncPrior is held exclusively during the time the savepoint records are being bypassed and the last one scavenged receives recEndChain. So I guess this cannot happen, currently. :) Kevin Christopher Powers wrote: > Kevin, > > This has to be most annoying assert in Falcon, next to the 'active' > asserts in the Record class. > Historically, this asserted because hasRecord() failed to thaw the > record, leaving the record state as 'recChilled'. In this case, however, > dup->state is 'recRollback'. > > Do you think we should we check for 'recRollback', too? > > bool Table::checkUniqueRecordVersion(...) > [...] > for (Record *dup = rec; dup; dup = dup->getPriorVersion()) > { > if (dup == record) > continue; // Check next record version > > // Get the record's transaction state. Don't wait yet. > state = transaction->getRelativeState(dup, DO_NOT_WAIT); > > // Check for a deleted record or a record lock > if (!dup->hasRecord()) > { > // If the record is a lock record, keep looking for a dup. > if (dup->state == recLock) > continue; // Next record version. > > // The record has been deleted. >>>> ASSERT(dup->state == recDeleted); <<< > > switch (state) > case CommittedVisible: > [...] > >