Bug #44911 | Falcon crashes with Error: Committed non-deleted record has no data buffer. | ||
---|---|---|---|
Submitted: | 15 May 2009 21:13 | Modified: | 26 May 2010 17:47 |
Reporter: | Olav Sandstå | Email Updates: | |
Status: | Unsupported | Impact on me: | |
Category: | MySQL Server: Falcon storage engine | Severity: | S2 (Serious) |
Version: | 6.0.12-alpha | OS: | Any |
Assigned to: | Kevin Lewis | CPU Architecture: | Any |
[15 May 2009 21:13]
Olav Sandstå
[15 May 2009 21:15]
Olav Sandstå
Setting to verified based on seeing it several times in pushbuild. Possible workaround: do not play with the chill threshold.
[15 May 2009 21:16]
Olav Sandstå
Also seen on Windows so believe this is not a Linux-only problem.
[18 May 2009 10:10]
Olav Sandstå
This crash has also happened several times when running the falcon_bug_34890 test using the latest source from mysql-6.0-falcon-team.
[18 May 2009 17:29]
Kevin Lewis
This FATAL message was added recently, (after 6.0.11) because this condition did not make sense. I figured that if it occurred, it should be understood. So now it is occurring, and I will try to understand why it happens. The previous action was to return NULL from fetchForUpdate, which has the effect of saying that this record number is not visible to the viewing transaction. If that is the correct action to take, this can easily be fixed.
[26 May 2009 9:17]
Olav Sandstå
With the extra information added by Kevin's latest patch the output when this crash occurs is now: [Falcon] Error: Committed non-deleted record has no data buffer. state=4, useCount=3, virtualOffset=0 where state=4 is (from Record.h): static const int recLock = 4; // this is a "record lock" and not a record From the core file the record version object has the following information: (dbx) print -r *rv *rv = { RecordVersion::Record::data = { RecordVersion::Record::record = (nil) } RecordVersion::Record::generation = 1ULL RecordVersion::Record::format = 0x18ab390 RecordVersion::Record::useCount = 3 RecordVersion::Record::recordNumber = 1137 RecordVersion::Record::size = 96 RecordVersion::Record::highWater = -13108 RecordVersion::Record::encoding = '\0' RecordVersion::Record::state = '\004' RecordVersion::priorVersion = 0x3817ba8 RecordVersion::virtualOffset = 0 RecordVersion::nextInTrans = 0x3819ba8 RecordVersion::prevInTrans = 0x3819aa8 RecordVersion::savePointId = 0 RecordVersion::superceded = true RecordVersion::transactionState = 0x45d8808 }
[26 May 2009 18:33]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/74976 2713 Kevin Lewis 2009-05-26 Bug#44911 - Suppose a call to fetchForUpdate is called for a base lockRecord returned from Table::fetch, but before it is evaluated, the lockRecord is superceded by an update record and the transaction is committed. FetchForUpdate will need to re-fetch the new committed record as if getRelativeState() had returned WasActive. But getRelativeState() returned CommittedVisible. That would have caused this FATAL condition that a "Committed non-deleted record has no data buffer". So a check for (source->state == recLock) needs to be done in order to re-fetch the base record. A lockRecord can still be linked to a transaction after the commit if it was updated at a higher savepoint. But they are always superceded with newer records. Regular lockRecords are unlinked fro transaction during the commit in the call to Transaction::releaseRecordLocks().
[2 Jun 2009 14:41]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/75470 2713 Kevin Lewis 2009-06-02 Bug#44911 - Suppose a call to fetchForUpdate is called for a base lockRecord returned from Table::fetch, but before it is evaluated, the lockRecord is superceded by an update record and the transaction is committed. FetchForUpdate will need to re-fetch the new committed record as if getRelativeState() had returned WasActive. But getRelativeState() returned CommittedVisible. That would have caused this FATAL condition that a "Committed non-deleted record has no data buffer". So a check for (source->state == recLock) needs to be done in order to re-fetch the base record. A lockRecord can still be linked to a transaction after the commit if it was updated at a higher savepoint. But they are always superceded with newer records. Regular lockRecords are unlinked from transactions during the commit in the call to Transaction::releaseRecordLocks(). So if a lock record is the base record and the transaction turns out to be committed, then the transaction must have been committed after the fetch. And it would only be CommittedVisible if the isolation was ReadCommitted or WriteCommitted. It would not happen with ConsistentRead.
[3 Jun 2009 21:01]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/75565 2718 Kevin Lewis 2009-06-03 Bug#44911 - More follow-on changes. This assures that there will not be a infinite loop in the case where a lock record is returned from Table::fetch and the transaction becomes CommittedVisible soon after. This should only occur once. The next time, it has to be a different lock record. If the same record is read again, something is fataly wrong. It happened once while I was making some changes for 43344 because of a mistake. So instead of looping infinitely reading the same record, this patch will issue a fatal error.