海山数据库(He3DB)源码详解:ResourceOwnerData及ResourceArray结构体解析
本文介绍了事务执行过程中,检查一个堆元组是否对当前事务可见,用于确保事务可以看到正确的数据版本。
ResourceOwnerData
结构体的作用
ResourceOwnerData
是 PostgreSQL 中用于管理资源所有权的核心结构体。它定义了一个资源所有者(ResourceOwner
)的内部数据结构,用于跟踪和管理事务或子事务中占用的各种资源。这些资源包括缓冲区、缓存引用、文件、锁等。以下是对 ResourceOwnerData
结构体及其成员的详细解读:
1. 树状结构
所有的ResourceOwnerData
数据会构成树状结构,如下图所示:
TopTransaction
作为父节点,通过firstchild
指针连接三个子节点;- 三个子节点分别通过
nextchild
指针构成链表;
2. 结构体定义
typedef struct ResourceOwnerData
{
ResourceOwner parent; /* NULL if no parent (toplevel owner) */
ResourceOwner firstchild; /* head of linked list of children */
ResourceOwner nextchild; /* next child of same parent */
const char *name; /* name (just for debugging) */
/* We have built-in support for remembering: */
ResourceArray bufferarr; /* owned buffers */
ResourceArray catrefarr; /* catcache references */
ResourceArray catlistrefarr; /* catcache-list pins */
ResourceArray relrefarr; /* relcache references */
ResourceArray planrefarr; /* plancache references */
ResourceArray tupdescarr; /* tupdesc references */
ResourceArray snapshotarr; /* snapshot references */
ResourceArray filearr; /* open temporary files */
ResourceArray dsmarr; /* dynamic shmem segments */
ResourceArray jitarr; /* JIT contexts */
ResourceArray cryptohasharr; /* cryptohash contexts */
ResourceArray hmacarr; /* HMAC contexts */
/* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */
int nlocks; /* number of owned locks */
LOCALLOCK *locks[MAX_RESOWNER_LOCKS]; /* list of owned locks */
} ResourceOwnerData;
复制
1. 树状结构成员
-
ResourceOwner parent;
- 类型:
ResourceOwner
(指向另一个ResourceOwnerData
的指针) - 作用:指向当前资源所有者的父节点。如果当前所有者是顶层所有者,则
parent
为NULL
。 - 用途:支持嵌套事务或子事务的资源管理。例如,在一个事务中开启一个子事务时,子事务的资源所有者会将父事务的资源所有者作为其
parent
。
- 类型:
-
ResourceOwner firstchild;
- 类型:
ResourceOwner
- 作用:指向当前资源所有者的第一个子节点。
- 用途:用于构建资源所有者的子节点链表,支持树状结构的遍历。
- 类型:
-
ResourceOwner nextchild;
- 类型:
ResourceOwner
- 作用:指向当前资源所有者的下一个兄弟节点。
- 用途:用于链表结构,支持遍历同一父节点的所有子节点。
- 类型:
-
const char *name;
- 类型:
const char*
- 作用:资源所有者的名称。
- 用途:主要用于调试,方便在日志或调试信息中标识资源所有者。
- 类型:
2. 资源管理相关成员
这些成员用于跟踪和管理不同类型的资源。每种资源类型都通过一个ResourceArray
数组来管理。
-
ResourceArray bufferarr;
- 作用:管理当前所有者占用的缓冲区资源。
- 用途:确保在事务结束时释放所有占用的缓冲区。
-
ResourceArray catrefarr;
- 作用:管理当前所有者对系统目录缓存(catcache)的引用。
- 用途:确保在事务结束时释放对系统目录缓存的引用。
-
ResourceArray catlistrefarr;
- 作用:管理当前所有者对系统目录缓存列表(catcache-list)的引用。
- 用途:确保在事务结束时释放对系统目录缓存列表的引用。
-
ResourceArray relrefarr;
- 作用:管理当前所有者对关系缓存(relcache)的引用。
- 用途:确保在事务结束时释放对关系缓存的引用。
-
ResourceArray planrefarr;
- 作用:管理当前所有者对计划缓存(plancache)的引用。
- 用途:确保在事务结束时释放对计划缓存的引用。
-
ResourceArray tupdescarr;
- 作用:管理当前所有者对元组描述符(tupdesc)的引用。
- 用途:确保在事务结束时释放对元组描述符的引用。
-
ResourceArray snapshotarr;
- 作用:管理当前所有者对快照(snapshot)的引用。
- 用途:确保在事务结束时释放对快照的引用。
-
ResourceArray filearr;
- 作用:管理当前所有者打开的临时文件。
- 用途:确保在事务结束时关闭所有临时文件。
-
ResourceArray dsmarr;
- 作用:管理当前所有者对动态共享内存段(dynamic shared memory segments)的引用。
- 用途:确保在事务结束时释放对动态共享内存段的引用。
-
ResourceArray jitarr;
- 作用:管理当前所有者对即时编译(JIT)上下文的引用。
- 用途:确保在事务结束时释放对JIT上下文的引用。
-
ResourceArray cryptohasharr;
- 作用:管理当前所有者对加密哈希上下文的引用。
- 用途:确保在事务结束时释放对加密哈希上下文的引用。
-
ResourceArray hmacarr;
- 作用:管理当前所有者对HMAC上下文的引用。
- 用途:确保在事务结束时释放对HMAC上下文的引用。
3. 锁管理相关成员
这些成员用于跟踪和管理当前所有者持有的锁。
-
int nlocks;
- 类型:
int
- 作用:当前所有者持有的锁的数量。
- 用途:记录当前所有者管理的锁的数量,确保在事务结束时释放所有锁。
- 类型:
-
LOCALLOCK *locks[MAX_RESOWNER_LOCKS];
- 类型:
LOCALLOCK*
数组 - 作用:存储当前所有者持有的锁的指针。
- 用途:确保在事务结束时释放所有持有的锁。
MAX_RESOWNER_LOCKS
是一个常量,限制了资源所有者可以持有的最大锁数量。
- 类型:
3. 总结
ResourceOwnerData
结构体是 PostgreSQL 中资源管理的核心组件,用于跟踪和管理事务或子事务中占用的各种资源。它的主要功能包括:
- 树状结构管理:通过
parent
、firstchild
和nextchild
成员,支持嵌套事务的资源管理。 - 资源跟踪:通过
ResourceArray
数组,管理不同类型的资源,确保在事务结束时释放所有资源。 - 锁管理:通过
nlocks
和locks
成员,跟踪和管理当前所有者持有的锁,确保在事务结束时释放所有锁。
通过这种设计,ResourceOwner
能够有效地管理资源的生命周期,确保资源在事务结束时被正确释放,从而避免资源泄漏和死锁问题。
ResourceArray
结构体的作用
ResourceArray
是 PostgreSQL 中用于存储和管理各种资源 ID 的通用结构体。它通过动态调整存储方式(从简单数组到哈希表)来高效地管理资源集合。以下是对 ResourceArray
结构体及其成员的详细解释:
1. 存储模式
ResourceArray
用于高效地存储和管理资源 ID。它支持以下两种存储模式:
- 简单数组模式:当资源数量较少时,使用线性数组存储资源 ID。
- 哈希表模式:当资源数量较多时,切换到哈希表存储,以提高查找效率。
这种设计结合了线性数组的简单性和哈希表的高效性,能够在不同场景下优化资源管理。
2. 结构体定义及成员
typedef struct ResourceArray
{
Datum *itemsarr; /* buffer for storing values */
Datum invalidval; /* value that is considered invalid */
uint32 capacity; /* allocated length of itemsarr[] */
uint32 nitems; /* how many items are stored in items array */
uint32 maxitems; /* current limit on nitems before enlarging */
uint32 lastidx; /* index of last item returned by GetAny */
} ResourceArray;
复制
-
Datum *itemsarr;
- 类型:
Datum
类型的指针数组。 - 作用:用于存储资源 ID 的数组。
- 说明:
- 在简单数组模式下,
itemsarr
是一个线性数组,存储资源 ID。 - 在哈希表模式下,
itemsarr
是一个哈希表,每个槽位存储一个资源 ID 或invalidval
。 Datum
是 PostgreSQL 中的通用数据类型,可以存储任意类型的数据。
- 在简单数组模式下,
- 类型:
-
Datum invalidval;
- 类型:
Datum
。 - 作用:表示无效值的标识符。
- 说明:
- 在哈希表模式下,
invalidval
用于标记空槽位或已删除的槽位。 - 当
itemsarr[k] == invalidval
时,表示该槽位是空的或无效的。
- 在哈希表模式下,
- 类型:
-
uint32 capacity;
- 类型:
uint32
(无符号 32 位整数)。 - 作用:表示
itemsarr
的分配长度(即数组或哈希表的总容量)。 - 说明:
- 在简单数组模式下,
capacity
是数组的最大长度。 - 在哈希表模式下,
capacity
是哈希表的总槽数。
- 在简单数组模式下,
- 类型:
-
uint32 nitems;
- 类型:
uint32
。 - 作用:表示当前存储的有效资源 ID 数量。
- 说明:
- 当
nitems
达到maxitems
时,数组或哈希表需要扩容。
- 当
- 类型:
-
uint32 maxitems;
- 类型:
uint32
。 - 作用:表示当前模式下
nitems
的上限。 - 说明:
- 在简单数组模式下,
maxitems
是数组的最大容量。 - 在哈希表模式下,
maxitems
是哈希表中允许存储的最大有效项数,通常小于capacity
,以避免哈希冲突过多。
- 在简单数组模式下,
- 类型:
-
uint32 lastidx;
- 类型:
uint32
。 - 作用:记录最近一次通过
GetAny
方法返回的资源 ID 的索引。 - 说明:
- 在
ResourceArrayRemove
方法中,lastidx
可以加快查找速度,避免重复搜索。
- 在
- 类型:
3. 工作原理
-
简单数组模式:
- 当资源数量较少时,
ResourceArray
使用线性数组存储资源 ID。 itemsarr
是一个线性数组,nitems
表示当前存储的资源数量。- 当
nitems
达到maxitems
时,切换到哈希表模式。
- 当资源数量较少时,
-
哈希表模式:
- 当资源数量较多时,
ResourceArray
使用哈希表存储资源 ID。 itemsarr
是一个哈希表,每个槽位存储一个资源 ID 或invalidval
。capacity
是哈希表的总槽数,maxitems
是允许存储的最大有效项数。- 如果
nitems
超过maxitems
,则扩容哈希表并重新哈希。
- 当资源数量较多时,
-
动态调整:
ResourceArray
会根据资源数量动态调整存储模式,以优化性能。- 在哈希表模式下,
lastidx
用于记录最近一次操作的索引,以加快查找速度。
4. 总结
ResourceArray
是一个高效管理资源 ID 的通用结构体,支持动态调整存储方式(从简单数组到哈希表)。它的成员变量分别用于:
- 存储资源 ID(
itemsarr
)。 - 标记无效值(
invalidval
)。 - 管理数组或哈希表的容量(
capacity
)。 - 记录当前存储的有效资源数量(
nitems
)。 - 设置存储上限(
maxitems
)。 - 记录最近一次操作的索引(
lastidx
)。
这种设计使得 ResourceArray
能够在不同场景下高效地管理资源,同时支持动态扩容和快速查找。