華為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函數,判斷待更新元組的狀態(tài),相比于HeapTupleSatisfiesNow函數只判斷元組是否有效,HeapTupleSatisfiesUpdate函數可以返回更多細節(jié)信息。

4.設置新元組的一系列信息,然后判斷是否需要toast操作(只會在當前數據表已經存在toast表或者插入的新元組過長超過了存放的閾值)獲得插入元組的頁面號。

5.備份舊元組,因為內存中的舊元組屬性可能會被修改,導致引起混淆。如果新元組在新page,需要設置新page的相關屬性

開始更新操作

6.調用RelationPutHeapTuple函數,將元組和linepoint插入到對應頁面的指定位置。

7.清理舊元組的infomask,并且設置元組的Xmax為當前事務,Cmax為當前命令,舊元組的t_ctid指向新元組。

8.設置buffer為臟塊

9.寫入日志

10.將元組在緩存中,設置為無效緩存,釋放緩存。

11.更新統(tǒng)計信息。

12.return TM_OK.

簡單的講

1.函數花了很大的功夫先判斷舊元組的狀態(tài),是否可以進行更新操作。

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函數,根據上述規(guī)則判斷當時時刻,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.寫日志。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容