+N Connection for root

これまで何度か、、「max_connectionsに達してしまったら、rootユーザ(DBAによる手動)によるログインもできないんでしょうか?」という質問を受け、その度に「mysqlでは無理っす」と答えていたのだけれども、、、、、、← 間違い

これを解消するパッチが登場し、MySQL本家がそれを取り込んだようです。

reserved_connectionsというシステム変数を新しく追加し、一般ユーザは"max_connections"まで、rootユーザは"max_connections + reserved_connections"に達するまで接続が可能となる。

バグではないのだけれども、パッチ取り込みの便宜上作られたバグレポート
http://bugs.mysql.com/bug.php?id=24826

Bitkeeperのcommitログ
http://lists.mysql.com/commits/19048

patchコードを見ると、普通にシステム変数を追加し、max_connections判定部分をいじっているだけのようだ。

ChangeSet@1.2359とのことだけど、まだmysql.bkbits.net上では見えない(のでたぶんbkから落としても入手はできない)。

しかしver5.0系に入ったようなので、次のリリースくらいから使えるようになるの鴨。朗報ですね♪

# なんか良く見ると+1だったのを+Nにするパッチみたいだな。+1の変更はいつはいったんだろ。。



結論:ずっと前からみたい
bkbitsでソースみたけど、ver4.0系まで遡ってもchangesetが1.1のものしかない。orz...

で、ついでなのでソースを追ってみた。

mysqld.ccのcreate_new_thread関数でmax_connectionsのチェックをしているようにも見えるのだけれども、、、

static void create_new_thread(THD *thd)
{
...(中略)...
  /* don't allow too many connections */
  if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop)
  {
    DBUG_PRINT("error",("Too many connections"));
    close_connection(thd, ER_CON_COUNT_ERROR, 1);
    delete thd;
    DBUG_VOID_RETURN;
  }
...(中略)...
}

実はこのifブロックに入るのはSUPERユーザでmax_connections+2に接続数が達する場合だけ。ちなみにthread_countってのは作成済み接続数。

ではSUPERではないユーザはどこで"Too many connectoins"と弾かれるのかというと、sql_parse.ccのcheck_user関数。

int check_user(THD *thd, enum enum_server_command command,
               const char *passwd, uint passwd_len, const char *db,
               bool check_count)
{
...(中略:ユーザ認証など)...
      if (check_count)
      {
        VOID(pthread_mutex_lock(&LOCK_thread_count));
        bool count_ok= thread_count <= max_connections + delayed_insert_threads
                       || (thd->main_security_ctx.master_access & SUPER_ACL);
        VOID(pthread_mutex_unlock(&LOCK_thread_count));
        if (!count_ok)
        {                                         // too many connections
          net_send_error(thd, ER_CON_COUNT_ERROR);
          DBUG_RETURN(-1);
        }
      }
...(中略)...
}

ここで、SUPER_ACL、すなわちSUPER権限がないとmax_connectionsにより弾かれる。

このときのbacktraceはこんな感じ。

#0  check_user (thd=0x8acd5a8, command=COM_CONNECT, passwd=0x8acea76 "", passwd_len=0, db=0x0, check_count=true) at sql_parse.cc:290
#1  0x081e5a6d in check_connection (thd=0x8acd5a8) at sql_parse.cc:1052
#2  0x081e5bfb in handle_one_connection (arg=0x8acd5a8) at sql_parse.cc:1142
#3  0xa7f53240 in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#4  0xa7bb832e in clone () from /lib/tls/i686/cmov/libc.so.6