其insert由函数heapam_tuple_insert完成。
1、首先需要从slot中取出tuple值,HeapTupleTableSlot.tuple
2、从relation中得到该记录即将插入表的OID:relation->rd_id,然后slot->tts_tableOid和tuple->t_tableOid更新为该OID
3、调用heap_insert将tuple插入heap 页中,这个过程中产生WAL日志并写入WAL BUFFER中:
1)生成事务ID:xid
2)调用函数heap_prepare_insert:设置tup->t_data的t_infomask和t_infomask2;tup->t_data->t_choice.t_heap.t_xmin为xid;
(tup->t_data)->t_choice.t_heap.t_field3.t_cid为入参cid
(tup->t_data)->t_choice.t_heap.t_xmax为0
即insert的xmin为事务ID,xmax为0
3)调用RelationGetBufferForTuple,从fsm中找到一个满足空间大小的数据页,并将该数据页加载到内存,返回内存块的块号Buffer
4)CheckForSerializableConflictIn隔离级别处理
5)调用RelationPutHeapTuple从页面中最后一个free slot并将记录插入。如何找free slot,PageAddItemExtended完成。
6)如果该页此时pd_flags & PD_ALL_VISIBLE,即该页内所有记录都可见,但此时插入了一个记录,需要清除该标签。
7)标记该buffer为脏页,以供后续checkpoint刷脏
8)生成WAL日志,并将WAL日志写入WAL BUFFER
9)将此时lsn写入页头pd_lsn
4、更新tuple->t_self为slot->tts_tid,即记录在页内位置。
如何在页内找一个free slot由函数PageAddItemExtended完成。
1、计算出pd_linp数组的最大值后新增一个后的个数:
limit=[pg_lower-sizeof(PageHeader)]/Sizeof(ItemIdData)+1
2、如果页头中pd_flags & PD_HAS_FREE_LINES为TRUE,即该数组中有free slot,那么首先从这个数组中找一个可用的ItemIdData,从pd_linp[0]开始一个一个的进行判断,一旦(itemId)->lp_flags == LP_UNUSED && (itemId)->lp_len != 0,表明这个slot可用,那么取这个offsetNumber返回
3、如果该页中没有free slot,则在pd_linp[limit-1]当前最后一个ItemIdData后面添加一个ItemIdData,设置该ItemIdData的值将其lp_off指向pd_upper位置并调整其lp_len=tuple->t_len,lp_flags = LP_NORMAL
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。