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.寫日志。