13719654321 发表于 2016-11-21 07:19:40

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
 *     Determinenumber of filedescriptorsthat 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);
}
页: [1]
查看完整版本: PostgreSQL启动过程中的那些事八:设置文件描述符个数