mariadb max_connections 设置无效问题

mariadb max_connections 设置无效

之前遇到设置了max_connections后无效,在网上查找后发现是由于系统的 open files 限制了其大小,可通过修改调大使其生效,但不太清楚其原理,就去看了下源码,现记录如下

源码分析

通过max_connections等值计算并设置max_open_files,若设置失败,可能调整max_connections的值 ,显示warning:Changed limits: max_open_files: xxx max_connections: xxx table_cache: xxx

  /* connections and databases needs lots of files */
  {
    uint files, wanted_files, max_open_files;

    /* MyISAM requires two file handles per table. */
    wanted_files= (10 + max_connections + extra_max_connections +
                   tc_size * 2);              //< 计算需要的files
    /*
      We are trying to allocate no less than max_connections*5 file
      handles (i.e. we are trying to set the limit so that they will
      be available).  In addition, we allocate no less than how much
      was already allocated.  However below we report a warning and
      recompute values only if we got less file handles than were
      explicitly requested.  No warning and re-computation occur if we
      can't get max_connections*5 but still got no less than was
      requested (value of wanted_files).
    */
    max_open_files= MY_MAX(MY_MAX(wanted_files,
                            (max_connections + extra_max_connections)*5),
                        open_files_limit);  //< 计算需要的files
    files= my_set_max_open_files(max_open_files);   //< 调用set_max_open_files(MY_MIN(files, OS_FILE_LIMIT))看max_open_files是否符合当前系统soft limit设置,不符,设置系统soft limit, 若失败返回soft limit;返回soft limit的值(无限制情况下为max_open_files)

    if (files < wanted_files)   //<  如果soft limit的值小于需要的值,则有问题
    {
      if (!open_files_limit || IS_SYSVAR_AUTOSIZE(&open_files_limit))
      {
          /// 如果open_files_limit设为0,或没有手动设置 则调整各变量值为默认值

        /*
          If we have requested too much file handles than we bring
          max_connections in supported bounds.
        */
        SYSVAR_AUTOSIZE(max_connections,
           (ulong) MY_MIN(files-10-TABLE_OPEN_CACHE_MIN*2, max_connections));  // 1)
            sql_print_warning("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
            files, max_connections, tc_size);
      }
      else if (global_system_variables.log_warnings)   ///< 不然warning(开启了warning),虽然没修改max_connections, 但最大连接数并不能到达max_connections ,会受系统soft limit限制
        sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
    }
    SYSVAR_AUTOSIZE(open_files_limit, files);
  }

#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)

#ifndef RLIM_INFINITY
#define RLIM_INFINITY ((uint) 0xffffffff)
#endif

static uint set_max_open_files(uint max_file_limit)
{
  struct rlimit rlimit;
  uint old_cur;
  DBUG_ENTER("set_max_open_files");
  DBUG_PRINT("enter",("files: %u", max_file_limit));

  if (!getrlimit(RLIMIT_NOFILE,&rlimit))  //< 获取系统对soft limit和hard limit的限制
  {
    old_cur= (uint) rlimit.rlim_cur;
    DBUG_PRINT("info", ("rlim_cur: %u  rlim_max: %u",
            (uint) rlimit.rlim_cur,
            (uint) rlimit.rlim_max));
    if ((ulonglong) rlimit.rlim_cur == (ulonglong) RLIM_INFINITY)  
        /// 如果soft limit为RLIM_INFINITY,也即不限制,则取设置的值max_file_limit  
        rlimit.rlim_cur = max_file_limit;
    if (rlimit.rlim_cur >= max_file_limit)
        /// 如果soft limit大于要设置的值,则取soft limit
        DBUG_RETURN(rlimit.rlim_cur);       /* purecov: inspected */

    /// 设置系统soft limit
    rlimit.rlim_cur= rlimit.rlim_max= max_file_limit;
    if (setrlimit(RLIMIT_NOFILE, &rlimit))
      /// 设置失败使用原先的soft limit
      max_file_limit= old_cur;      /* Use original value */
    else
    {  /// 成功,则为max_file_limit
      rlimit.rlim_cur= 0;           /* Safety if next call fails */
      (void) getrlimit(RLIMIT_NOFILE,&rlimit);
      DBUG_PRINT("info", ("rlim_cur: %u", (uint) rlimit.rlim_cur));
      if (rlimit.rlim_cur)              /* If call didn't fail */
    max_file_limit= (uint) rlimit.rlim_cur;
    }
  }
  DBUG_PRINT("exit",("max_file_limit: %u", max_file_limit));
  DBUG_RETURN(max_file_limit);
}

#else
static uint set_max_open_files(uint max_file_limit)
{
  /* We don't know the limit. Return best guess */
  return MY_MIN(max_file_limit, OS_FILE_LIMIT);
}
#endif

总结

mariadb 的 max_connections 的设置会受到系统soft limit的限制,如果没有手动设置open_files_limit ,若max_connections 设置后所需的files 大于soft limit,且尝试修改soft limit为此值失败,mariadb 会调整max_connections值为(ulong) MY_MIN(files-10-TABLE_OPEN_CACHE_MIN*2, max_connections)) TABLE_OPEN_CACHE_MIN为400。如果手动设置了open_files_limit,则不会调整max_connections等值,会显示warning,但实际的 max_connections 仍受 soft limit 限制

你可能感兴趣的:(max_connections,mariadb,soft,limit,mysql,数据库)