本篇内容介绍了“PostgreSQL中BufTableInsert函数有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
一、数据结构
BufferDesc
共享缓冲区的共享描述符(状态)数据
//buffer header锁定
#define BM_LOCKED (1U << 22)
//数据需要写入(标记为DIRTY)
#define BM_DIRTY (1U << 23)
//数据是有效的
#define BM_VALID (1U << 24)
//已分配buffer tag
#define BM_TAG_VALID (1U << 25)
//正在R/W
#define BM_IO_IN_PROGRESS (1U << 26)
//上一个I/O出现错误
#define BM_IO_ERROR (1U << 27)
//开始写则变DIRTY
#define BM_JUST_DIRTIED (1U << 28)
//存在等待sole pin的其他进程
#define BM_PIN_COUNT_WAITER (1U << 29)
//checkpoint发生,必须刷到磁盘上
#define BM_CHECKPOINT_NEEDED (1U << 30)
//持久化buffer(不是unlogged或者初始化fork)
#define BM_PERMANENT (1U << 31)
typedef struct BufferDesc
{
//buffer tag
BufferTag tag;
//buffer索引编号(0开始),指向相应的buffer pool slot
int buf_id;
//tag状态,包括flags/refcount和usagecount
pg_atomic_uint32 state;
//pin-count等待进程ID
int wait_backend_pid;
//空闲链表链中下一个空闲的buffer
int freeNext;
//缓冲区内容锁
LWLock content_lock;
} BufferDesc;
BufferTag
Buffer tag标记了buffer存储的是磁盘中哪个block
typedef struct buftag
{
//物理relation标识符
RelFileNode rnode;
ForkNumber forkNum;
//相对于relation起始的块号
BlockNumber blockNum;
} BufferTag;
HTAB
哈希表的顶层控制结构.
struct HTAB
{
//指向共享的控制信息
HASHHDR *hctl;
//段开始目录
HASHSEGMENT *dir;
//哈希函数
HashValueFunc hash;
//哈希键比较函数
HashCompareFunc match;
//哈希键拷贝函数
HashCopyFunc keycopy;
//内存分配器
HashAllocFunc alloc;
//内存上下文
MemoryContext hcxt;
//表名(用于错误信息)
char *tabname;
//如在共享内存中,则为T
bool isshared;
//如为T,则固定大小不能扩展
bool isfixed;
//不允许冻结共享表,因此这里会保存相关状态
bool frozen;
//保存这些固定值的本地拷贝,以减少冲突
//哈希键长度(以字节为单位)
Size keysize;
//段大小,必须为2的幂
long ssize;
//段偏移,ssize的对数
int sshift;
};
struct HASHHDR
{
FreeListData freeList[NUM_FREELISTS];
//这些域字段可以改变,但不适用于分区表
//同时,就算是非分区表,共享表的dsize也不能改变
//目录大小
long dsize;
//已分配的段大小(<= dbsize)
long nsegs;
//正在使用的最大桶ID
uint32 max_bucket;
//进入整个哈希表的模掩码
uint32 high_mask;
//进入低于半个哈希表的模掩码
uint32 low_mask;
//下面这些字段在哈希表创建时已固定
//哈希键大小(以字节为单位)
Size keysize;
//所有用户元素大小(以字节为单位)
Size entrysize;
//分区个数(2的幂),或者为0
long num_partitions;
//目标的填充因子
long ffactor;
//如目录是固定大小,则该值为dsize的上限值
long max_dsize;
//段大小,必须是2的幂
long ssize;
//端偏移,ssize的对数
int sshift;
//一次性分配的条目个数
int nelem_alloc;
#ifdef HASH_STATISTICS
long accesses;
long collisions;
#endif
};
typedef struct
{
//该空闲链表的自旋锁
slock_t mutex;
//相关桶中的条目个数
long nentries;
//空闲元素链
HASHELEMENT *freeList;
} FreeListData;
typedef struct HASHELEMENT
{
//链接到相同桶中的下一个条目
struct HASHELEMENT *link;
//该条目的哈希函数结果
uint32 hashvalue;
} HASHELEMENT;
//哈希表头部结构,非透明类型,用于dynahash.c
typedef struct HASHHDR HASHHDR;
//哈希表控制结构,非透明类型,用于dynahash.c
typedef struct HTAB HTAB;
//hash_create使用的参数数据结构
//根据hash_flags标记设置相应的字段
typedef struct HASHCTL
{
//分区个数(必须是2的幂)
long num_partitions;
//段大小
long ssize;
//初始化目录大小
long dsize;
//dsize上限
long max_dsize;
//填充因子
long ffactor;
//哈希键大小(字节为单位)
Size keysize;
//参见上述数据结构注释
Size entrysize;
//
HashValueFunc hash;
HashCompareFunc match;
HashCopyFunc keycopy;
HashAllocFunc alloc;
MemoryContext hcxt;
//共享内存中的哈希头部结构地址
HASHHDR *hctl;
} HASHCTL;
//哈希桶是HASHELEMENTs链表
typedef HASHELEMENT *HASHBUCKET;
//hash segment是桶数组
typedef HASHBUCKET *HASHSEGMENT;
typedef uint32 (*HashValueFunc) (const void *key, Size keysize);
typedef int (*HashCompareFunc) (const void *key1, const void *key2,
Size keysize);
typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize);
typedef void *(*HashAllocFunc) (Size request);
BufferLookupEnt
//检索hash表的条目
typedef struct
{
//磁盘page的tag
BufferTag key;
//相关联的buffer ID
int id;
} BufferLookupEnt;
二、源码解读
BufTableInsert源码很简单,重点是需要理解HTAB数据结构,即全局变量SharedBufHash的数据结构.
int
BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
{
BufferLookupEnt *result;
bool found;
Assert(buf_id >= 0);
Assert(tagPtr->blockNum != P_NEW);
//static HTAB *SharedBufHash;
result = (BufferLookupEnt *)
hash_search_with_hash_value(SharedBufHash,
(void *) tagPtr,
hashcode,
HASH_ENTER,
&found);
if (found)
return result->id;
result->id = buf_id;
return -1;
}
三、跟踪分析
测试脚本,查询数据表:
10:01:54 (xdb@[local]:5432)testdb=# select * from t1 limit 10;
启动gdb,设置断点
(gdb)
(gdb) b BufTableInsert
Breakpoint 1 at 0x875c92: file buf_table.c, line 125.
(gdb) c
Continuing.
Breakpoint 1, BufTableInsert (tagPtr=0x7fff0cba0ef0, hashcode=1398580903, buf_id=101) at buf_table.c:125
125 Assert(buf_id >= 0);
(gdb)
输入参数
tagPtr-BufferTag结构体
hashcode=1398580903,
buf_id=101
(gdb) p *tagPtr
$1 = {rnode = {spcNode = 1663, dbNode = 16402, relNode = 51439}, forkNum = MAIN_FORKNUM, blockNum = 0}
调用hash_search_with_hash_value,重点考察SharedBufHash(HTAB指针)
(gdb) n
129 hash_search_with_hash_value(SharedBufHash,
SharedBufHash
(gdb) p *SharedBufHash
$2 = {hctl = 0x7f5489004380, dir = 0x7f54890046d8, hash = 0xa3bf74 <tag_hash>, match = 0x4791a0 <memcmp@plt>,
keycopy = 0x479690 <memcpy@plt>, alloc = 0x89250b <ShmemAllocNoError>, hcxt = 0x0,
tabname = 0x1fbf1d8 "Shared Buffer Lookup Table", isshared = true, isfixed = false, frozen = false, keysize = 20,
ssize = 256, sshift = 8}
(gdb)
SharedBufHash->hctl,HASHHDR结构体
freeList是一个数组
num_partitions是分区个数,默认为128
(gdb) p *SharedBufHash->hctl
$3 = {freeList = {{mutex = 0 '\000', nentries = 3, freeList = 0x7f5489119700}, {mutex = 0 '\000', nentries = 2,
freeList = 0x7f548912d828}, {mutex = 0 '\000', nentries = 4, freeList = 0x7f54891418d8}, {mutex = 0 '\000',
nentries = 3, freeList = 0x7f5489155a00}, {mutex = 0 '\000', nentries = 8, freeList = 0x7f5489169a38}, {
mutex = 0 '\000', nentries = 3, freeList = 0x7f548917dc00}, {mutex = 0 '\000', nentries = 5,
freeList = 0x7f5489191cb0}, {mutex = 0 '\000', nentries = 3, freeList = 0x7f54891a5e00}, {mutex = 0 '\000',
nentries = 1, freeList = 0x7f54891b9f50}, {mutex = 0 '\000', nentries = 3, freeList = 0x7f54891ce000}, {
mutex = 0 '\000', nentries = 3, freeList = 0x7f54891e2100}, {mutex = 0 '\000', nentries = 5,
freeList = 0x7f54891f61b0}, {mutex = 0 '\000', nentries = 4, freeList = 0x7f548920a2d8}, {mutex = 0 '\000',
nentries = 2, freeList = 0x7f548921e428}, {mutex = 0 '\000', nentries = 2, freeList = 0x7f5489232528}, {
mutex = 0 '\000', nentries = 4, freeList = 0x7f54892465d8}, {mutex = 0 '\000', nentries = 3,
freeList = 0x7f548925a700}, {mutex = 0 '\000', nentries = 3, freeList = 0x7f548926e800}, {mutex = 0 '\000',
nentries = 5, freeList = 0x7f54892828b0}, {mutex = 0 '\000', nentries = 2, freeList = 0x7f5489296a28}, {
mutex = 0 '\000', nentries = 4, freeList = 0x7f54892aaad8}, {mutex = 0 '\000', nentries = 4,
freeList = 0x7f54892bebd8}, {mutex = 0 '\000', nentries = 5, freeList = 0x7f54892d2cb0}, {mutex = 0 '\000',
nentries = 0, freeList = 0x7f54892e6e78}, {mutex = 0 '\000', nentries = 2, freeList = 0x7f54892faf28}, {
mutex = 0 '\000', nentries = 3, freeList = 0x7f548930f000}, {mutex = 0 '\000', nentries = 4,
freeList = 0x7f54893230d8}, {mutex = 0 '\000', nentries = 4, freeList = 0x7f54893371d8}, {mutex = 0 '\000',
nentries = 2, freeList = 0x7f548934b328}, {mutex = 0 '\000', nentries = 1, freeList = 0x7f548935f450}, {
mutex = 0 '\000', nentries = 4, freeList = 0x7f54893734d8}, {mutex = 0 '\000', nentries = 3,
freeList = 0x7f5489387600}}, dsize = 512, nsegs = 512, max_bucket = 131071, high_mask = 262143, low_mask = 131071,
keysize = 20, entrysize = 24, num_partitions = 128, ffactor = 1, max_dsize = 512, ssize = 256, sshift = 8,
nelem_alloc = 51}
(gdb)
(gdb) p *SharedBufHash->hctl->freeList[0].freeList
$4 = {link = 0x7f54891196d8, hashvalue = 0}
(gdb) p *SharedBufHash->hctl->freeList[0].freeList.link
$5 = {link = 0x7f54891196b0, hashvalue = 0}
(gdb)
SharedBufHash->dir,段开始目录
(gdb) p *SharedBufHash->dir
$6 = (HASHSEGMENT) 0x7f5489005700
(gdb) p **SharedBufHash->dir
$7 = (HASHBUCKET) 0x0
(gdb) p *SharedBufHash->dir[0]
$8 = (HASHBUCKET) 0x0
(gdb) p *SharedBufHash->dir[1]
$9 = (HASHBUCKET) 0x0
(gdb)
哈希函数为tag_hash
哈希键比较函数是memcmp
@plt
哈希键拷贝函数是memcpy
@plt
内存分配器是ShmemAllocNoError
内存上下文为NULL
表名是Shared Buffer Lookup Table
共享内存(isshared=T)
非固定/非冻结/哈希键长度为20B/段大小为256/段偏移为8
执行hash_search_with_hash_value,查看相关信息
(gdb) n
128 result = (BufferLookupEnt *)
(gdb)
135 if (found)
(gdb) p *SharedBufHash
$10 = {hctl = 0x7f5489004380, dir = 0x7f54890046d8, hash = 0xa3bf74 <tag_hash>, match = 0x4791a0 <memcmp@plt>,
keycopy = 0x479690 <memcpy@plt>, alloc = 0x89250b <ShmemAllocNoError>, hcxt = 0x0,
tabname = 0x1fbf1d8 "Shared Buffer Lookup Table", isshared = true, isfixed = false, frozen = false, keysize = 20,
ssize = 256, sshift = 8}
(gdb) p *SharedBufHash->hctl
$11 = {freeList = {{mutex = 0 '\000', nentries = 3, freeList = 0x7f5489119700}, {mutex = 0 '\000', nentries = 2,
freeList = 0x7f548912d828}, {mutex = 0 '\000', nentries = 4, freeList = 0x7f54891418d8}, {mutex = 0 '\000',
nentries = 3, freeList = 0x7f5489155a00}, {mutex = 0 '\000', nentries = 8, freeList = 0x7f5489169a38}, {
mutex = 0 '\000', nentries = 3, freeList = 0x7f548917dc00}, {mutex = 0 '\000', nentries = 5,
freeList = 0x7f5489191cb0}, {mutex = 0 '\000', nentries = 4, freeList = 0x7f54891a5dd8}, {mutex = 0 '\000',
nentries = 1, freeList = 0x7f54891b9f50}, {mutex = 0 '\000', nentries = 3, freeList = 0x7f54891ce000}, {
mutex = 0 '\000', nentries = 3, freeList = 0x7f54891e2100}, {mutex = 0 '\000', nentries = 5,
freeList = 0x7f54891f61b0}, {mutex = 0 '\000', nentries = 4, freeList = 0x7f548920a2d8}, {mutex = 0 '\000',
nentries = 2, freeList = 0x7f548921e428}, {mutex = 0 '\000', nentries = 2, freeList = 0x7f5489232528}, {
mutex = 0 '\000', nentries = 4, freeList = 0x7f54892465d8}, {mutex = 0 '\000', nentries = 3,
freeList = 0x7f548925a700}, {mutex = 0 '\000', nentries = 3, freeList = 0x7f548926e800}, {mutex = 0 '\000',
nentries = 5, freeList = 0x7f54892828b0}, {mutex = 0 '\000', nentries = 2, freeList = 0x7f5489296a28}, {
mutex = 0 '\000', nentries = 4, freeList = 0x7f54892aaad8}, {mutex = 0 '\000', nentries = 4,
freeList = 0x7f54892bebd8}, {mutex = 0 '\000', nentries = 5, freeList = 0x7f54892d2cb0}, {mutex = 0 '\000',
nentries = 0, freeList = 0x7f54892e6e78}, {mutex = 0 '\000', nentries = 2, freeList = 0x7f54892faf28}, {
mutex = 0 '\000', nentries = 3, freeList = 0x7f548930f000}, {mutex = 0 '\000', nentries = 4,
freeList = 0x7f54893230d8}, {mutex = 0 '\000', nentries = 4, freeList = 0x7f54893371d8}, {mutex = 0 '\000',
nentries = 2, freeList = 0x7f548934b328}, {mutex = 0 '\000', nentries = 1, freeList = 0x7f548935f450}, {
mutex = 0 '\000', nentries = 4, freeList = 0x7f54893734d8}, {mutex = 0 '\000', nentries = 3,
freeList = 0x7f5489387600}}, dsize = 512, nsegs = 512, max_bucket = 131071, high_mask = 262143, low_mask = 131071,
keysize = 20, entrysize = 24, num_partitions = 128, ffactor = 1, max_dsize = 512, ssize = 256, sshift = 8,
nelem_alloc = 51}
(gdb) p **SharedBufHash->dir
$12 = (HASHBUCKET) 0x0
(gdb) p *SharedBufHash->dir
$13 = (HASHSEGMENT) 0x7f5489005700
(gdb) p result
$14 = (BufferLookupEnt *) 0x7f54891a5e10
(gdb) p *result
$15 = {key = {rnode = {spcNode = 1663, dbNode = 16402, relNode = 51439}, forkNum = MAIN_FORKNUM, blockNum = 0}, id = 0}
(gdb) p found
$16 = false
完成调用,返回
(gdb) n
138 result->id = buf_id;
(gdb)
140 return -1;
(gdb)
141 }
(gdb)
BufferAlloc (smgr=0x204f430, relpersistence=112 'p', forkNum=MAIN_FORKNUM, blockNum=0, strategy=0x0,
foundPtr=0x7fff0cba0fa3) at bufmgr.c:1216
1216 if (buf_id >= 0)
(gdb)
“PostgreSQL中BufTableInsert函数有什么作用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!