Bug #47487 Falcon; validateUpdate asserts where an uncommitted record has no prior record.
Submitted: 21 Sep 2009 15:21 Modified: 26 May 2010 17:46
Reporter: Kevin Lewis Email Updates:
Status: Unsupported Impact on me:
None 
Category:MySQL Server: Falcon storage engine Severity:S3 (Non-critical)
Version: OS:Any
Assigned to: Kevin Lewis CPU Architecture:Any
Tags: F_RECORD TREE

[21 Sep 2009 15:21] Kevin Lewis
Description:
While running DBT2, The following assert happened;

bool Table::validateUpdate(int32 recordNumber, TransId transactionId)
{
. . .
	Record *next = record->getPriorVersion();
	if (!next)
		{
		Log::debug("Table::validateUpdate: bad record\n");
		initial->print();
		Record *newRecord = fetch(recordNumber);
		Log::debug("Table::validateUpdate: currentRecord\n");
		newRecord->print();
		ASSERT(false);   <-- CRASHED HERE
		}

Falcon] Error: assertion (false) failed at line 3855 in file Table.cpp

Error::error(char const*, ...)+0x109)
Table::validateUpdate(int,unsigned int)+0x12c)
Section::updateRecord(int,Stream*, unsigned int, bool)+0x4c)
Dbb::updateRecord(int,int, Stream*, unsigned int, bool)+0x45)
SRLUpdateRecords::commit()+0x1aa)
SerialLogTransaction::commit()+0x131)  
Gopher::gopherThread()+0x165)

How to repeat:
Run DBT2

Suggested fix:
This new assertion may be related to the new feature of the scavenger within Falcon that snips invisible intermediate records.  It was recently added and this assert was not seen before that.
[21 Sep 2009 15:23] Kevin Lewis
Verified from call stack of serveral DBT2 runs.
[22 Sep 2009 15:34] Kevin Lewis
I just caught this assert in the debugger.  The record being completed by the gopher thread is the base record. It has no prior record, which means that the prior was snipped.  It was most likely not pruned because the oldest active transaction was 80.  

I could either try to prevent pruning and snipping if the younger visible record is not yet completed (Transaction::writePending == true) or delete this assert and allow Table::validateUpdate() to assume that if there is no priorVersion, then it must have been there at one time and is now missing because it was completed ahead of this younger record version.
[22 Sep 2009 17:09] 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/84166

2793 Kevin Lewis	2009-09-22
      Bug #47487- Falcon; validateUpdate asserts where an uncommitted
      record has no prior record.
      
      This situation is now possible due to pruning and most likely, 
      snipping intermediate records. So the error condition and assert 
      is now gone.  
      
      In addition, RecordScavenge::canBeSnipped is improved to assure 
      that any record that is snipped is not only committed, but also 
      completed.
     @ storage/falcon/RecordScavenge.cpp
        Bug #47487 - RecordScavenge::canBeSnipped is improved to assure 
        that any record that is snipped is not only committed, but also 
        completed.
     @ storage/falcon/RecordScavenge.h
        Bug #47487 - RecordScavenge::canBeSnipped is improved to assure 
        that any record that is snipped is not only committed, but also 
        completed.
     @ storage/falcon/RecordVersion.cpp
        Bug #47487 - RecordScavenge::canBeSnipped is improved to assure 
        that any record that is snipped is not only committed, but also 
        completed.
[22 Sep 2009 17:27] 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/84169

2795 Kevin Lewis	2009-09-22
      Bug#47487 - In RecordScavenge::canBeSnipped(), make sure
      that the transactionStates are not NULL.
     @ storage/falcon/RecordScavenge.cpp
        Bug#47487 - In RecordScavenge::canBeSnipped(), make sure
        that the transactionStates are not NULL.