现在的位置: 首页 > 综合 > 正文

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

2013年05月19日 ⁄ 综合 ⁄ 共 2034字 ⁄ 字号 评论关闭

        这一节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

 *     Determinenumber of filedescriptors that fd.c is allowed to use

 */

void

set_max_safe_fds(void)

{

    int        usable_fds;

    int        already_open;

 

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

     * We want to setmax_safe_fds to

     *         MIN(usable_fds, max_files_per_process - already_open)

     * less the slop factor forfiles that are opened without consulting

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

     * or theexperimentally-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 FDsreserved for system() etc.

     */

    max_safe_fds -= NUM_RESERVED_FDS;

 

    /*

     * Make sure we still haveenough to get by.

     */

    if (max_safe_fds < FD_MINFREE)

       ereport(FATAL,

              (errcode(ERRCODE_INSUFFICIENT_RESOURCES),

               errmsg("insufficient file descriptors available to startserver 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);

}

抱歉!评论已关闭.