设为首页 收藏本站
查看: 1305|回复: 0

[经验分享] PostgreSQL启动过程中的那些事七:初始化共享内存和信号七:shmem中初始化bufferpool

[复制链接]

尚未签到

发表于 2016-11-21 07:50:38 | 显示全部楼层 |阅读模式
       pg初始化完shmem,给其加上索引"ShmemIndex"后,接着就在shmem里初始化管理各种事务和事务本身相关结构的实例。然后就是初始化缓冲池(buffer pool)。
       缓冲区(buffers)存在于一个空闲内存块列表和一个哈希表查询数据结构。下面简述一下和缓冲池相关的概念。
       查找缓冲区(buffer)时必须注意,在I/O开始之前缓冲区必须可用。负责尝试读缓冲区的第二个进程会分配自己的复制,这样缓冲池就不一致了。
       缓冲区同步,IO_IN_PROGRESS——这是缓冲区描述符里的一个标签。当一个IO被启动和在IO结束被清除时必须设置该标签。这样是为了保证在另一个进程使用该缓冲区的时候其他进程不能开始使用该缓冲区。

    缓冲区缓冲块的引用计数——计进程在缓冲区上持有pin的数目。缓冲区在IO期间,BufferAlloc()之后立即被pin住。事务结束之前pin被释放。

    私有引用计数——每一个缓冲区有一个私有的引用计数,保持当前进程里pin住该缓冲区的次数跟踪。用这个有两个目的:第一,如果pin住一个缓冲区多于一次,pg仅需要改变共享的引用计数一次,这样只锁共享状态一次;第二,当事务退出时,它应该仅unpin缓冲区正好自己pin住该缓冲区的次数,这样该事务就可以不破坏了另一个后台进程/backend的缓冲区。

 
1先上个图,看一下函数调用过程梗概,中间略过部分细节
 
DSC0000.bmp



初始化缓冲池/bufferpool方法调用流程图

  
 

  
2初始化xlog相关结构
  
话说main()->…->PostmasterMain()->…->reset_shared()-> CreateSharedMemoryAndSemaphores()->…-> InitBufferPool(),初始化缓冲池及相关数据结构BufferDesc等,然后又初始化了一个可扩展哈希表"shared bufferlookup table",用作内存里管理缓冲池。
  
InitBufferPool()->ShmemInitStruct(),在其中调用hash_search()在哈希表索引"ShmemIndex"中查找"Buffer Descriptors",如果没有,就在shmemIndex中给"Buffer Descriptors"分一个HashElement和ShmemIndexEntentry),在其中的Entry中写上"Buffer Descriptors"。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给"Buffer Descriptors"相关结构(是该结构的数组,数组数目根据shared_buffer计算,有数万甚至数十万以上,具体见下面“BufferPool相关结构和策略控制结构图”)分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小,最后返回InitBufferPool(),让BufferDesc *类型全局变量BufferDescriptors指向BufferDesc类型实例的起始地址就是在shmem里给"Buffer Descriptors"相关结构分配的内存起始地址,设置其中BufferDesc结构类型的成员值。
  
接着InitBufferPool()->ShmemInitStruct(),在其中调用hash_search()在哈希表索引"ShmemIndex"中查找"Buffer Blocks",如果没有,就在shmemIndex中给"Buffer Blocks"分一个HashElement和ShmemIndexEntentry),在其中的Entry中写上"Buffer Blocks"。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给"Buffer Blocks"分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小。每个缓冲区块大小默认为8k(可以根据设置变),共shared_buffer/BLCKSZ个,一般会有数万个甚至数十万个以上,一个缓冲区块一个BufferDescriptors。最后返回InitBufferPool(),让char *类型全局变量BufferBlocks指向该内存段的起始地址。
  
然后StrategyInitialize()->InitBufferTable()->ShmemInitHash(),在其中创建一个用于管理和查找缓冲区块的可扩展哈希表"shared bufferlookup table"(图在下面)。返回InitBufferPool(),让HTAB *类型全局静态变量SharedBufHash指向"shared bufferlookup table"
  
最后StrategyInitialize()->ShmemInitStruct(),在其中调用hash_search()在哈希表索引"ShmemIndex"中查找"Buffer StrategyStatus",如果没有,就在shmemIndex中给"Buffer Strategy Status"分一个HashElement和ShmemIndexEntentry),在其中的Entry中写上"Buffer Strategy Status"。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给"Buffer Strategy Status"相关结构(见下面“BufferPool相关结构和策略控制结构图”)分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小,最后返回StrategyInitialize(),让BufferStrategyControl *类型全局静态变量StrategyControl指向BufferStrategyControl类型实例的起始地址就是在shmem里给"Buffer Strategy Status"相关结构分配的内存起始地址,设置其中BufferStrategyControl结构类型的成员值。
  
相关变量、结构定义和初始化完成后数据结构图在下面。
  
 
  
typedefstruct sbufdesc

  
{

  
       BufferTag      tag;                     /* ID of page contained inbuffer */

  
       BufFlags       flags;                   /* see bit definitions above*/

  
       uint16           usage_count;     /* usage counter for clock sweep code */

  
       unsigned     refcount;             /* # of backends holding pins onbuffer */

  
       int                 wait_backend_pid;        /* backend PID of pin-count waiter */

  
 

  
       slock_t          buf_hdr_lock;     /* protects the above fields */

  
 

  
       int                 buf_id;                /* buffer's index number (from 0) */

  
       int                 freeNext;             /* link in freelist chain */

  
 

  
       LWLockId     io_in_progress_lock;  /* to wait for I/O to complete */

  
       LWLockId     content_lock;     /* to lock access to buffer contents */

  
}BufferDesc;

  
 

  
/*

  
 * The sharedfreelist control information.

  
 */

  
typedef struct

  
{

  
    /* Clock sweep hand: index of next buffer to considergrabbing */

  
    int         nextVictimBuffer;

  
 

  
    int         firstFreeBuffer;    /* Head of list ofunused buffers */

  
    int         lastFreeBuffer;/* Tail of list of unused buffers */

  
 

  
    /*

  
     * NOTE: lastFreeBuffer is undefined whenfirstFreeBuffer is -1 (that is,

  
     * when the list is empty)

  
     */

  
 

  
    /*

  
     * Statistics. These counters should be wide enough that they can't

  
     * overflow during a single bgwriter cycle.

  
     */

  
    uint32      completePasses;     /* Complete cycles of the clock sweep*/

  
    uint32      numBufferAllocs;    /* Buffers allocated since last reset*/   

  
} BufferStrategyControl;

  
 

  
/* Pointers to shared state */

  
static BufferStrategyControl *StrategyControl = NULL;

  
 

  
static HTAB *SharedBufHash;

  
 

  
typedef struct buftag

  
{

  
    RelFileNodernode;          /* physical relationidentifier */

  
    ForkNumberforkNum;

  
    BlockNumberblockNum;       /* blknum relative tobegin of reln */

  
} BufferTag;

  
 

  
typedef struct

  
{

  
    BufferTag   key;            /* Tag of a disk page */

  
    int         id;             /*Associated buffer ID */

  
} BufferLookupEnt;

  
 


DSC0001.bmp

初始化完BufferPool相关结构的内存结构图

DSC0002.bmp

BufferPool哈希表索引“Shared Buffer Lookup Table”

  
DSC0003.bmp

BufferPool相关结构和策略控制结构图

       上图中左面是BufferPool和策略控制结构图,根据shared_buffer的设置,有25600和BufferDesc数组和25600个bufferblock数组,还有一个BufferStrategyControl结构。右面是25600和BufferDesc数组中每个BufferDesc的成员的初始化值。已经体现了一个bufferblock两个轻量锁以及和磁盘上的数据文件的对应情况。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-303132-1-1.html 上篇帖子: PostgreSQL启动过程中的那些事七:初始化共享内存和信号六:shmem中初始化twophase 下篇帖子: PostgreSQL启动过程中的那些事七:初始化共享内存和信号九:shmem中初始化Predicate锁
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表