PostgreSQL启动过程中的那些事八:设置文件描述符个数

这一节 pg postmaster 启动时估算数据库的要打开的文件数,设置VFD数。

Pg 用“虚拟”文件描述符( VFDs )缓存来处理打开的文件。因各种原因服务器打开很多文件描述符,包括基表、临时文件(例如排序和 hash spool files )和像那样随机对 C 例程库的调用;超过系统对单进程能打开的文件数的限制是很容易的。操作系统打开一个文件占用一个文件描述符( FD )。(在现代 OS 上这个值大概是 256 ,但是在其他 OS 上可能低至 32 WinServer2003 里是 512

根据实际 OS 文件描述符按需打开或关闭, “虚拟”文件描述符 由该 LRU Last Recently Used ,最近最少使用)池管理。明显的, 如果一个文件通过这套接口打开,所有后续操作必须也通过这套接口操作(文件类型不是一个真实的文件描述符)。

为了该机制能工作,服务器上的大多数(如果不是所有)文件打开应该使用这些接口来代替 C 函数库(例如 open(2) fopen(3) )。负责, pg 可以发现实际文件描述符( FD )不够用。

这个事情我赶上过,数据库不是 pg ,在一个用户的生产环境上报数据库的 license 文件已过期,但实际上 license 文件是永不过期。后来定位是因为数据库频繁操作 license 文件时没有使用 VFD 这套接口, FD 达到了 OS 系统对单进程能打开的文件数的限制引起的,所以有了另一片博文《 Windows 系统进程打开文件句柄数的限制 》,解决办法是使用这套接口操作或者使用 C 函数打开后及时使用 C 函数关闭。

 

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

 

设置 VFD 方法调用流程图


2 设置 max_safe_fds

话说 main()-> ->PostmasterMain()-> -> set_max_safe_fds () ,设置了最大可用的 VFD ,具体只是计算相关数字,没有涉及相关管理的数据结构,所以把代码贴出来

/*

  * set_max_safe_fds

  *     Determine number of filedescriptors that fd.c is allowed to use

  */

void

set_max_safe_fds ( void )

{

    int         usable_fds;

    int         already_open;

 

    /*----------

      * We want to set max_safe_fds to

      *         MIN(usable_fds, max_files_per_process - already_open)

      * less the slop factor for files that are opened without consulting

      * fd.c.  This ensures that we won't exceed either max_files_per_process

      * or the experimentally-determined EMFILE limit.

      *----------

      */

    count_usable_fds(max_files_per_process,

                    &usable_fds, &already_open);

 

    max_safe_fds = Min(usable_fds, max_files_per_process - already_open);

 

    /*

      * Take off the FDs reserved for system() etc.

      */

    max_safe_fds -= NUM_RESERVED_FDS;

 

    /*

      * Make sure we still have enough to get by.

      */

    if (max_safe_fds < FD_MINFREE)

       ereport(FATAL,

              (errcode(ERRCODE_INSUFFICIENT_RESOURCES),

                errmsg( "insufficient file descriptors available to start server process" ),

                errdetail( "System allows %d, we need at least %d." ,

                        max_safe_fds + NUM_RESERVED_FDS,

                        FD_MINFREE + NUM_RESERVED_FDS)));

 

    elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d" ,

         max_safe_fds, usable_fds, already_open);

}

猜你喜欢

转载自beigang.iteye.com/blog/1536932
今日推荐