查询流程:
以 Select c2 from tb1 where c1 = 1为例:
1、根据索引找到TID(1,2)的元组指针,即linePointer。
2、计算其事务xid是否可见,在Map中计算其csn和快照csn的大小关系。
3、如果大于快照CSN,那么不可见,判断还有没有undo链,如果有,执行第4步,如果没有?(刚刚创建???);如果可见,返回。
4、查看元组的TD字段,得到创建该元组时对应的事务槽索引ID。如果之前未进入undo链,那么遍历这个链,执行第5步。如果之前进入过undo链,那么比较二者的索引ID是否相同,如果不同就从这个新的undo链开始遍历。如果相同就???
5、然后从对应的事务槽中不断按照链表的形式,从新往旧找(按照block pre pointer指针),直到找到第一个满足页块号和偏移量等于TID(1,2)的元组,执行第2步。
为什么这样查找?
1、事务槽是存在复用的,并不是一个事务槽始终被一个事务占据,所以一个元组在不断更新的操作中,可能会对应不同的事务槽,也就是需要从不同的undo链中跳来跳去,直到找到满足元组指针(偏移量)和可见性都满足的元组。
2、当一个事务修改元组时,事务在一个事务槽中,会把旧元组移到该事务槽对应的undo链中,然后在堆表中产生一个新元组。也就是说如果要找到一个堆表中元组的上一个版本,那么必然在其指向的事务槽undo链中!