POSTGRESQL 存储管理之外存管理(一)(jung)

来源:互联网 发布:切特尼克知乎 编辑:程序博客网 时间:2024/05/24 07:46

一、前言:

    本文通过打开和修改postgresql 数据库中的表文件,理解pg数据库中存储管理之外存管理smgr实现机制。


二、smgr 实现机制

   smgr 实现机制如下图所示:




        smgr对外封装了各种辅助存储介质的管理,但目前源代码中只实现了磁盘存储器的管理;smgr的接口函数在smgr.c文件中,而其中很多的接口其实是直接调用磁盘存储管理器的操作(md.c),磁盘存储管理器只是对虚拟文件描述符进行操作,而实际对物理文件的操作是通过  fd.c  中的函数实现的。



三、代码实现:每一层的主要数据结构

        smgr.c ----> SMgrRelationData 

----> SMgrRelation

----> SMgrRelationHash

SMgrRelationData 是最基本的数据结构,表征了一个表文件;

SMgrRelationSMgrRelationData的表头

 SMgrRelationHashSMgrRelationData 中第一个成员值作为关键字,SMgrRelationData为成员变量的哈希表,便于查找和打开表文件


typedef struct SMgrRelationData{/* rnode is the hashtable lookup key, so it must be first! */RelFileNodeBackend smgr_rnode;/* relation physical identifier *//* pointer to owning pointer, or NULL if none */struct SMgrRelationData **smgr_owner;/* * These next three fields are not actually used or manipulated by smgr, * except that they are reset to InvalidBlockNumber upon a cache flush * event (in particular, upon truncation of the relation).Higher levels * store cached state here so that it will be reset when truncation * happens.  In all three cases, InvalidBlockNumber means "unknown". */BlockNumber smgr_targblock; /* current insertion target block */BlockNumber smgr_fsm_nblocks;/* last known size of fsm fork */BlockNumber smgr_vm_nblocks;/* last known size of vm fork *//* additional public fields may someday exist here *//* * Fields below here are intended to be private to smgr.c and its * submodules.Do not touch them from elsewhere. */intsmgr_which;/* storage manager selector */boolsmgr_transient;/* T if files are to be closed at EOXact *//* for md.c; NULL for forks that are not open */struct _MdfdVec *md_fd[MAX_FORKNUM + 1];} SMgrRelationData;


SMgrRelationData 个成员变量的解析:
1、smgr_rnode 是关系的物理标识符,同时它也是SMgrRelationHash表的关键字;
2、smgr_owner (属主指针,SMgrRelationData参考对象,)
3、smgr_targblock ,smgr_fsm_nblocks ,smgr_vm_nblocks 是表文件,fsm,vm文件的块数,
初始化的时候为InvalidBlockNumber
4、smgr_which   选择存储管理器,0 表示磁盘
5、smgr_transient   和事务有关系
6、md_fd 虚拟文件描述符Vfd链表



md.c ----> MdfdVec 将表文件的各段连接起来,
typedef struct _MdfdVec{Filemdfd_vfd;/* fd number in fd.c's pool */BlockNumber mdfd_segno;/* segment number, from 0 */struct _MdfdVec *mdfd_chain;/* next segment, or NULL */} MdfdVec;


fd.c ---->Vfd

---->VfdCache Vfd数组

typedef struct vfd{intfd;/* current FD, or VFD_CLOSED if none */unsigned short fdstate;/* bitflags for VFD's state */ResourceOwner resowner;/* owner, for automatic cleanup */FilenextFree;/* link to next free VFD, if in freelist */FilelruMoreRecently;/* doubly linked recency-of-use list */FilelruLessRecently;off_tseekPos;/* current logical file position */char   *fileName;/* name of file, or NULL for unused VFD *//* NB: fileName is malloc'd, and must be free'd when closing the VFD */intfileFlags;/* open(2) flags for (re)opening the file */intfileMode;/* mode to pass to open(2) */} Vfd;

根据该数据结构中nextFree 实现空闲Vfd链表Free List,根据lruMoreRecently,lruLessRecently实现LRU池,从而有效的管理Vfd,实现对文件的访问数量不受操作系统的实现


四、如何实现表文件的打开?

(1)、smgropen()(smgr.c) 初始化SMgrRelationHash
(2)、smgrcreate()(smgr.c) 调用mdcreate()
mdcreate()(md.c)为该表文件创建一个SMgrRelationData,主要描述该表文件的空间OID,所在数据库OID以及自身的OID
(3)、smgrread() (smgr.c)开始读取表文件的某文件块;
----_mdfd_getseg() (md.c)找到包含指定文件块的文件段
----FileSeek()确认寻址是否正确定位到该段的目标文件块起始地址(该函数位于fd.c中,实际操作物理文件)
----FileRead()将目标文件块读取到预先分配好的缓存中(该函数位于fd.c中,实际操作物理文件),接下来就是内存管理部分了。


同理修改并保存一个表文件的主要的区别就是在打开表文件的基础之上,调用smgrwrite()
smgrwrite():
----_mdfd_getseg() (md.c)找到包含指定文件块的文件段
----FileSeek()确认寻址是否正确定位到该段的目标文件块起始地址(该函数位于fd.c中,实际操作物理文件)
----FileWrite()(fd.c)将缓存中的的文件块写入到相应的磁盘空间中去。



具体实现细节待续。。。。


原创粉丝点击