每一个数据块的头部存在ITL信息(interested transaction list),其中的每一项是影响这个数据块的事务信息。而在每一行中都存在一个lock byte,其中存储着ITL槽的信息。因此,当想查询某一行的事务信息时,可以根据byte lock查找ITL槽中的事务ID,然后根据事务ID从回滚段中的事务表中查询事务信息。
1. Read the Data Block.
2. Read the Row Header.
3. Check the Lock Byte to determine whether there's an ITL entry.
4. Read the ITL entry to determine the Transaction ID (Xid).
5. Read the Transaction Table using the Transaction ID. If the transaction has been committed and has a System Commit Number less than the query's System Change Number, update the status of the block (block cleanout) and start over at step 1.
6. Read the last undo block (Uba).
7. Compare the block transaction ID with the transaction table transaction ID. If the Transaction ID in the undo block doesn't equal the Transaction ID from the Transaction Table, then issue ORA-1555, Snapshot Too Old.
8. If the Transaction IDs are identical, make a copy of the data block in memory. Starting with the head undo entry, apply the changes to the copied data block.
9. If the tail undo entry (the actual first undo entry in the chain, or the last in the chain going backwards!) indicates another data block address, read the indicated undo block into memory and repeat steps 7 and 8 until the undo entries don't contain a value for the data block address.
10. When there's no "previous data block address," the transaction has been completely undone.
11. If the undo entry contains:
a. a pointer to a previous transaction undo block address, read the Transaction ID in the previous transaction undo block header and read the appropriate Transaction Table entry. Return to step 5.
b. an ITL record, restore the ITL record to the data block. Return to step 4.
参考:
http://www.jlcomp.demon.co.uk/cleanout.html
http://www.ixora.com.au/tips/admin/ora-1555.htm
将一致读的步骤细化一点,请指正:
从第5步开始:
IF 在Transaction Table 中根据Transaction ID 找到transaction
IF transaction 已经commit
IF query scn>commit scn
则接受该块,进行clean out,返回1
ELSEIF query scn 则进行一致性读,从第8步向后执行
ELSEIF transaction 没有commit
也进行一致性读,从第8步向后执行
ELSEIF 在Transaction Table 中没有找到transaction(回滚信息被覆盖了,也说明事务已经提交,因为只有提交后所在的undo extent才能被覆盖。这样query scn则去比较control scn。control scn是指事务表中最近一次被重用的transaction slot的前一个事务的commit scn,也就是事务表中所能找到的最小的commit scn了)
IF query scn 则无法知道query scn和commit scn得大小关系,出现ORA-01555错误
IF query scn>control scn
则query scn肯定>commit scn
则接受该块,进行clean out,并将block 中ITL标记上“U”,表示“upper bound commit” ,并返回1