OpenGauss ustore查询过程的流程

在这里插入图片描述
查询流程:
以 Select c2 from tb1 where c1 = 1为例:
1、根据索引找到TID(1,2)的元组指针,即linePointer。
2、计算其事务xid是否可见,在Map中计算其csn和快照csn的大小关系。
3、如果大于快照CSN,那么不可见,判断还有没有undo链,如果有,执行第4步,如果没有,返回查询无结果;如果可见,返回。
4、查看元组的TD字段,得到该元组上一个版本时对应的事务槽索引td_id,从该链首位置开始遍历,遍历流程见第5步。
5、然后从对应的事务槽中不断按照链表的形式,从新往旧找(按照block pre pointer指针),直到找到第一个满足页块号和偏移量等于TID(1,2)的元组,执行第2步。

为什么这样查找?
1、事务槽是存在复用的,并不是一个事务槽始终被一个事务占据,所以一个元组在不断更新的操作中,可能会对应不同的事务槽,也就是需要从不同的undo链中跳来跳去,直到找到满足元组指针(偏移量)和可见性都满足的元组。
2、当一个事务修改元组时,事务在一个事务槽中,会把旧元组移到该事务槽对应的undo链中,然后在堆表中产生一个新元组。也就是说如果要找到一个堆表中元组的上一个版本,那么必然在其指向的事务槽undo链中!

为什么每次切换回滚链都从链首开始回滚,能够保证在寻找历史版本数据时不会遍历同一个回滚链两次?
答:同一个事务有没有可能在同一条链上产生多个历史版本数据呢?答案是可能的,比如
一个事务T1(槽1)执行了1次更新操作;
事务T2(槽2)又对其执行了一次更新;
T3占据了和T1同样的事务槽(槽1),执行了一次更新;
T4占据了槽2,执行了一次更新。
同时在遍历过程中,有可能出现找到一半就跳转去另外一个链的情况。这样两条链之间跳来跳去,为了避免出现死循环,在判断undo_record时,除了要确保blkno和offset相同,还需要确保undo_record的xid互相一致。具体操作时在切换到一个新链时,一直往上寻找的过程中必须找到xid与上次找到的undo_record中的OldXid相同的undo_record。
示例:

CREATE TABLE t(id int,age int) WITH (INIT_TD=2);

begin;

insert into t values(1,1);

update t set age=45 where id=1;

commit;

tdslot=1

长事务

start transaction isolation level repeatable read;

select * from t where id=1;

这一步仅查询不会分配事务目录



update t set age=67 where id=1;

tdslot=2

update t set age=84 where id=1;

tdslot=1

update t set age=101 where id=1;

tdslot=1

update t set age=121 where id=1;

tdslot=2

此时在长事务中执行查询操作就会发现上文中出现的逻辑

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值