华为openGauss数据库源码解析——堆表操作(3)

heap_update函数

参数:(Relation relation, Relation parentRelation, ItemPointer otid, HeapTuple newtup, CommandId cid, Snapshot crosscheck, bool wait, TM_FailureData *tmfd, bool allow_update_self)

relation指的是需要更新元组的数据表,parentRelation是父数据表(???),otid指向待更新的元组,newtup是新的元组,cid更新的命令id,crosscheck快照,wait表示是否等待冲突的更新提交或者失败。

原作者指出最好使用simple_heap_update函数进行元组更新

1.调用RelationGetIndexAttrBitmap函数获取parentRelation或者 relation数据表的rd_indexattr和rd_idattr参数,这些参数储存着数据表的索引信息(哪几列有索引)。

2.根据数据表relation以及itempoint,获取旧的元组

3.调用HeapTupleSatisfiesUpdate函数,判断待更新元组的状态,相比于HeapTupleSatisfiesNow函数只判断元组是否有效,HeapTupleSatisfiesUpdate函数可以返回更多细节信息。

4.设置新元组的一系列信息,然后判断是否需要toast操作(只会在当前数据表已经存在toast表或者插入的新元组过长超过了存放的阈值)获得插入元组的页面号。

5.备份旧元组,因为内存中的旧元组属性可能会被修改,导致引起混淆。如果新元组在新page,需要设置新page的相关属性

开始更新操作

6.调用RelationPutHeapTuple函数,将元组和linepoint插入到对应页面的指定位置。

7.清理旧元组的infomask,并且设置元组的Xmax为当前事务,Cmax为当前命令,旧元组的t_ctid指向新元组。

8.设置buffer为脏块

9.写入日志

10.将元组在缓存中,设置为无效缓存,释放缓存。

11.更新统计信息。

12.return TM_OK.

简单的讲

1.函数花了很大的功夫先判断旧元组的状态,是否可以进行更新操作。

2.然后又去判断新元组是否可以存放在同一页以及是否需要toast功能

3.调用RelationPutHeapTuple函数,真正的将新元组插入到页面中

4.写日志

simple_heap_update函数

当不希望同时更新目标元组时,此函数可用于更新元组

参数:(Relation relation, ItemPointer otid, HeapTuple tup)

调用simple_heap_update函数,只需要提供三个参数,然后也是借用heap_update函数完成功能的实现,但是其他参数不用自己传入。

1.判断要修改的元组是否是“内置功能”,内置功能的元组不能修改。

2.调用heap_update函数,

heap_update(relation, NULL, otid, tup, GetCurrentCommandId(true),
                         InvalidSnapshot, true /* wait for commit */, &tmfd);

3.根据heap_update函数返回的TM_Result类型,获取更新操作的完成情况。

当前有效的tuple是指

((Xmin == my-transaction && 元组由当前事务插入 and

* Cmin < my-command && 插入的命令号小于当前的命令号 and

* (Xmax is null || 元组没有被删除 or

* (Xmax == my-transaction && 元组由当前事务删除 and

* Cmax >= my-command))) 删除事务的命令号大于当前的命令号

* || or or

* (Xmin is committed && 元组被其他已经提交的事务插入, and

* (Xmax is null || 元组没有被删除or

* (Xmax == my-transaction && 元组由当前事务删除 and

* Cmax >= my-command) || 删除的命令号大于当前命令号, or

* (Xmax != my-transaction && 删除元组不是当前事务 and

* Xmax is not committed)))) 删除元组的事务还没有提交

HeapTupleSatisfiesNow函数,根据上述规则判断当时时刻,tuple是否有效。

heap_lock_tuple函数

参数:(Relation relation, HeapTuple tuple, Buffer* buffer, CommandId cid, LockTupleMode mode, bool nowait, TM_FailureData *tmfd, bool allow_lock_self)

函数结果:

HeapTupleMayBeUpdated: lock was successfully acquired

HeapTupleSelfUpdated: lock failed because tuple updated by self

HeapTupleUpdated: lock failed because tuple updated by other xact

作用:对元组上共享锁或者排他锁。

对元组加锁之前,必须要获取buffer pin

heap_inplace_update函数

参数:(Relation relation, HeapTuple tuple)

tuple里面的t_self指向待更新的元组,而tuple自己里面存的是新元组

作用:原地更新元组,但是违反了MVCC和事务安全性,所以使用场景非常少。由于不能修改tuple的大小,我们只修改tuple的数据部分,不修改null bitmap和其他元组头部数据。

1.检查tuple是否合法以及原tuple和新tuple的大小是否相等,不合法或者不相等直接返回.

2.因为占用内存的空间相同,直接调用memcpy_s函数,将新元组这一块内存块拷贝过来,覆盖原来旧元组的位置

3.写日志。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

allwellright

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值