postgres 源码解析47 元组的删除流程 heap_delete
在PostgreSQL中,元组的删除是通过heap_delete
函数来实现的。这个函数定义在src/backend/access/heap/heapam.c
文件中。
以下是heap_delete
函数的核心步骤:
- 检查是否有活跃的事务,如果没有,则开启一个新的事务。
- 获取元组所在的页面,如果页面不在内存中,则从磁盘加载。
- 在页面的可用空间中记录删除操作,这通过设置元组的t\_ctid为InvalidTransactionId和t\_infomask为DEADBIT来标记元组为删除。
- 如果页面满足清理条件(例如页面满足最小空闲空间),则进行VACUUM操作以清理页面上的已删除元组。
- 如果删除导致了页面的变化,则需要在相关的索引中删除引用该元组的索引项。
- 如果删除的是堆的根元组(即表的第一个元组),则需要更新相关的空闲空间映射。
- 如果事务需要被复制,则记录XLOG日志以便于恢复。
以下是一个简化的heap_delete
函数实现的例子:
// 删除元组的核心函数
void
heap_delete(Relation relation, ItemPointer tid, Snapshot snapshot,
HeapTupleCallback callback, void *callback_state)
{
// 获取元组
HeapTupleHeader tuple = (HeapTupleHeader) PageGetItem(page, line_offset);
// 设置元组为删除
tuple->t_ctid = InvalidTransactionId; // 设置为无效的事务ID
tuple->t_infomask |= HEAP_XMAX_INVALID; // 设置XMAX为无效
tuple->t_infomask |= HEAP_IS_DEAD; // 设置元组为DEAD
// 如果需要,执行VACUUM操作
if (PageIsFull(page))
{
// 执行VACUUM操作
}
// 如果事务需要被复制,记录XLOG日志
if (RelationNeedsWAL(relation))
{
// 写入XLOG日志
}
// 如果有回调函数,调用回调函数
if (callback)
{
// 调用回调函数
}
}
这个例子省略了许多细节,如空间的回收、并发控制、日志记录等,但它提供了一个对heap_delete
函数功能的高层次理解。
评论已关闭