My opinion is that we aught to find a way to thaw any record in the
record cache before it becomes unthawable if it needs to be viewed.
In other words, any record that is visible to any transaction should be
thawable or already thawed.
So let's look at how some chilled records can currently get into this
predicament where we cannot thaw them.
Imagine a record with a bunch of old record versions;
Chain RecState TransID TransState WriteComplete
0 recDeleted 300 Committed Yes
1 recChilled 150 Committed Yes
2 recChilled 100 Committed Yes
3 Record N/A N/A N/A
Now let's imagine that Transaction 305 started before 300 finished and
305 is still active. It has a dependency on 300 and so 300 continues to
have a chain of RecordVersions attached to it. Because of the
dependency count in 150, Transaction::commitRecords did not get called
when 150 went through Transaction::writeComplete.
If transaction 305 wanted to read this record, it would first fetch the
base record, determine that it is not visible, and then fetch the prior
record. This record version is visible. But it is chilled. In order to
thaw this record, the current code would get it from the data page, but
since the base record is already committed and write complete, the page
does not contain the record. It is deleted.
Maybe it can be thawed from the serial log still. Maybe, but there is
no guarantee that the serial log has not been switched after 150 went
write complete. We need to find an appropriate time to thaw these
records before the page get written over by a deleted or updated record.
Note that if the newest record is DELETED like this example, the current
code hits an assert trying to thaw it from the page since the record
does not exist. But if the newest record is just UPDATED, I believe
that we are thawing the wrong version of the record!
Let's look at the older record version in the chain; #2. It was never
thawed, and it never needed to be. What good luck! This is an example
of why we do not want to thaw everything that goes writeComplete. We
chilled it to save memory, so why fill up the record cache again if we
don't HAVE to. This record version and the one originally read from the
file, #3, will be scavenged during the next cycle. #2 will get
scavenged if it is older than the record version that is visible to the
oldest currently active transaction. (Right Ann?)
So when do we thaw these records that MAY be read in the future? I
think it must be done when a newer version is put into the data page.
That includes when a record is deleted from the page. This way we do
not have to rely on the serial log to thaw old versions. That means
that somewhere in SRLUpdateRecords::redo(), before we overwrite a record
in a page, we need to thaw the prior record version if it is still chilled.
Ann has another theory on how a record version may be unthawable. Maybe
she can present that...
Kevin Lewis
Falcon team Lead