我的编程空间,编程开发者的网络收藏夹
学习永远不晚

PostgreSQL VFD机制

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

PostgreSQL VFD机制

1、结构体

VFD机制中由结构体struct vfd来维护。其中各个成员变量的意义如下表所示:

fd

vfd实际对应的物理文件文件描述符

fdstate

FD_DELETE_AT_CLOSE:表示文件在关闭时需删除

FD_TEMP_FILE_LIMIT:标记临时文件

FD_CLOSE_AT_EOXACT:

这几个都针对临时文件

resowner

owner, for automatic cleanup

nextFree

VFD的free链表,实际上是数组的下标。

lruMoreRecently

VFD的最近最少使用链表,为双向。实际上也是数组的下标

lruLe***ecently

lruLe***ecently为正向,每次插入都插入头部

fileSize

文件大小

fileName

文件名

fileFlags

打开文件时的标签,比如O_CREATE等

fileMode

打开文件时的属性,比如读写权限等

2、初始化

启动时初始化,使用malloc,只在本进程中有效,即每个进程都维护各自的VfdCache而并非共享内存。初始化时只申请第一个数组,并将其fd置为VFD_CLOSED。

PostgresMain->BaseInit->InitFileAccess:
    VfdCache = (Vfd *) malloc(sizeof(Vfd));
    MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
    VfdCache->fd = VFD_CLOSED;
    SizeVfdCache = 1;

2、open时的流程

1)Open时首先会调用AllocateVfd,从VfdCache数组中找一个空闲的slot,然后返回。该函数流程见AllocateVfd调用。

2)然后会调用ReleaseLruFiles判断是否open了最大限制的fd。如超出限制,则将LRU链表最后一个VFD的fd close掉。

3)open文件,并将该VFD插入到LRU链表。插入LRU的函数Insert详细流程看下面的函数分析。

4)然后对vfdP成员变量进行赋值。

PathNameOpenFilePerm->
    file = AllocateVfd();
    vfdP = &VfdCache[file];
    ReleaseLruFiles();
    vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
    Insert(file);
    vfdP->fileName = fnamecopy;
    
    vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
    vfdP->fileMode = fileMode;
    vfdP->fileSize = 0;
    vfdP->fdstate = 0x0;
    vfdP->resowner = NULL;

AllocateVfd

1)每次调用BasicOpenFilePerm open文件前都会调用AllocateVfd从VfdCache中获取一个空闲的vfd。

2)首先会判断free链表中是否为空。初始时刻,SizeVfdCache为1,则会将VfdCache初始化成大小32的数组,并将其通过nextFree串联起来形成free链表,注意该free链表为循环。

3)VfdCache[0]不使用。最开始32个的时候,即第一次扩充后free 链表如下图所示,跳过VfdCache[1],1会返回。也就是说每次取VFD都是 VfdCache[0].nextFree

4)后续再次扩充时,都是翻倍进行扩充

AllocateVfd->
    if (VfdCache[0].nextFree == 0){
        Size  newCacheSize = SizeVfdCache * 2;
        if (newCacheSize < 32)
            newCacheSize = 32;
        newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
        VfdCache = newVfdCache;
        for (i = SizeVfdCache; i < newCacheSize; i++){
            MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
            VfdCache[i].nextFree = i + 1;
            VfdCache[i].fd = VFD_CLOSED;
        }
        VfdCache[newCacheSize - 1].nextFree = 0;
        VfdCache[0].nextFree = SizeVfdCache;
        SizeVfdCache = newCacheSize;
    }
    file = VfdCache[0].nextFree;
    VfdCache[0].nextFree = VfdCache[file].nextFree;
    return file;

PostgreSQL VFD机制

ReleaseLruFiles

1)nfile为open打开的文件数,numAllocatedDescs为fopen打开的文件数,max_safe_fds为操作系统计算得出的值。

2)一旦超出max_safe_fds值,就会调用ReleaseLruFile从LRU链表删除一个,注意删除的是VfdCache[0].lruMoreRecently,即链表的尾部,最近最少使用的。

3)首先将该fd关闭,然后将之置为VFD_CLOSED。调用Delete函数将VFD从LRU链表删除。注意这里只是从LRU链表删除,不会释放回收到free链表,也不会修改vfd数据结构的其他成员变量值。因为后续可能还会用到该物理文件,会重新open并将之重新insert到LRU链表。

ReleaseLruFiles->
    while (nfile + numAllocatedDescs >= max_safe_fds){
        if (!ReleaseLruFile())
           break;
    }
ReleaseLruFile->
    LruDelete(VfdCache[0].lruMoreRecently);->
        vfdP = &VfdCache[file];
        close(vfdP->fd);
        vfdP->fd = VFD_CLOSED;
        --nfile;
        Delete(file);-->
            vfdP = &VfdCache[file];
            VfdCache[vfdP->lruLe***ecently].lruMoreRecently = vfdP->lruMoreRecently;
            VfdCache[vfdP->lruMoreRecently].lruLe***ecently = vfdP->lruLe***ecently;

3、Insert

Insert->
    vfdP = &VfdCache[file];
    vfdP->lruMoreRecently = 0;
    vfdP->lruLe***ecently = VfdCache[0].lruLe***ecently;
    VfdCache[0].lruLe***ecently = file;
    VfdCache[vfdP->lruLe***ecently].lruMoreRecently = file;

 

LRU链表的形式如下:

PostgreSQL VFD机制

Insert一个VFD时:

PostgreSQL VFD机制

4、Delete

Delete(file);-->
    vfdP = &VfdCache[file];
    VfdCache[vfdP->lruLe***ecently].lruMoreRecently = vfdP->lruMoreRecently;
    VfdCache[vfdP->lruMoreRecently].lruLe***ecently = vfdP->lruLe***ecently;

例如删除VfdCache[1]:

PostgreSQL VFD机制

5、回收VFD

1)每次调用FileClose时,会回收vfd到free链表。

2)先调用close函数

3)然后将之从LRU链表删除

4)如果是临时文件,还会将临时文件删除

5)调用FreeVfd将vfd回收到free链表

FileClose->
    close(vfdP->fd);
    --nfile;
    vfdP->fd = VFD_CLOSED;
    Delete(file);
    ...
    FreeVfd(file);

 

FreeVfd

调用函数FreeVfd回收,注意几个成员变量的修改。回收时,将之插入到free链表头部。注意每次取时也从头部取

FreeVfd->
    free(vfdP->fileName);//注意fileName需要释放,他是另malloc的
    vfdP->fileName = NULL;
    vfdP->fdstate = 0x0;
    vfdP->nextFree = VfdCache[0].nextFree;
    VfdCache[0].nextFree = file;


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

PostgreSQL VFD机制

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

PostgreSQL的事务管理机制是什么

PostgreSQL的事务管理机制是基于ACID(原子性、一致性、隔离性、持久性)特性的。它支持事务的原子性,即事务中的所有操作要么全部成功提交,要么全部失败回滚;一致性,即事务执行前后数据库的状态保持一致;隔离性,即多个事务之间应该是相互
PostgreSQL的事务管理机制是什么
2024-04-09

PostgreSQL免费公开课第17期-full-page写操作机制

十七、PostgreSQL full-page写操作机制 1、阐述full-page写操作特点 2、为什么要full-page写操作 3、什么时候进行full-page写操作 4、与其它数据库类似技术的对比 full-page写操作是PG数据库一个特别的技术,
PostgreSQL免费公开课第17期-full-page写操作机制
2015-10-16

postgresql强制删除数据库

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname="db_name" AND pidpg_backend_pid();drop datab
postgresql强制删除数据库
2016-10-14

PostgreSQL的同步流复制配置

1.PostgreSQL主备数据库的同步设置主要涉及如下文件: 1. pg_hba.conf                 postgresql 主库访问规则文件2. postgresql.conf            postgresql 主库配置文件
2019-11-24

PostgreSQL使用repmgr配置级联复制

最近的项目要求配置共享存储的四节点集群,使集群能够形成负载均衡。 但是大家知道,PostgreSQL不支持使用同一数据目录生成多个实例,在执行pg_ctl start的时候,如果指定的数据目录有实例在运行,则该实例会发生错误导致数据库down掉。故而,我们选择
PostgreSQL使用repmgr配置级联复制
2021-07-15

PostgreSQL中如何实现主从复制

要实现PostgreSQL中的主从复制,可以按照以下步骤进行操作:配置主服务器:首先在主服务器上打开postgresql.conf文件,设置参数wal_level为hot_standby,max_wal_senders为至少1,和wal_k
PostgreSQL中如何实现主从复制
2024-04-09

编程热搜

目录