地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【MySQL】Too many connectionsとrds_superuser_roleの小ネタ

dev.classmethod.jp

よさそうなアップデートを見つけてテンション上がったが多分思ったのではなさそうというので調べた。

こういうのがなくなると思ったがrdsadminというユーザーがrdsの色々面倒を見てくれてるやつがいるので必ず救われるというわけではなさそうという感じだった。

qiita.com

rdsadminユーザーの権限

> show grants for 'rdsadmin'@'localhost'\G
*************************** 1. row ***************************
Grants for rdsadmin@localhost: GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO `rdsadmin`@`localhost` WITH GRANT OPTION
*************************** 2. row ***************************
Grants for rdsadmin@localhost: GRANT APPLICATION_PASSWORD_ADMIN,AUDIT_ABORT_EXEMPT,AUDIT_ADMIN,AUTHENTICATION_POLICY_ADMIN,BACKUP_ADMIN,BINLOG_ADMIN,BINLOG_ENCRYPTION_ADMIN,CLONE_ADMIN,CONNECTION_ADMIN,ENCRYPTION_KEY_ADMIN,FIREWALL_EXEMPT,FLUSH_OPTIMIZER_COSTS,FLUSH_STATUS,FLUSH_TABLES,FLUSH_USER_RESOURCES,GROUP_REPLICATION_ADMIN,INNODB_REDO_LOG_ARCHIVE,INNODB_REDO_LOG_ENABLE,PASSWORDLESS_USER_ADMIN,PERSIST_RO_VARIABLES_ADMIN,REPLICATION_APPLIER,REPLICATION_SLAVE_ADMIN,RESOURCE_GROUP_ADMIN,RESOURCE_GROUP_USER,ROLE_ADMIN,SENSITIVE_VARIABLES_OBSERVER,SERVICE_CONNECTION_ADMIN,SESSION_VARIABLES_ADMIN,SET_USER_ID,SHOW_ROUTINE,SYSTEM_USER,SYSTEM_VARIABLES_ADMIN,TABLE_ENCRYPTION_ADMIN,TELEMETRY_LOG_ADMIN,XA_RECOVER_ADMIN ON *.* TO `rdsadmin`@`localhost` WITH GRANT OPTION

Too many connectionsのエラーとは

mysqld サーバーに接続しようとしたときにクライアントで Too many connections エラーが発生した場合、使用可能なすべての接続が他のクライアントによって使用されています。

許可される接続数は、max_connections システム変数によって制御されます。 より多くの接続をサポートするには、max_connections をより大きな値に設定します。

MySQL :: MySQL 8.0 リファレンスマニュアル :: B.3.2.5 接続が多すぎます

と、書いてある。実際どう言う時にエラーになるのかを調べていく

MySQLはシングルプロセス・マルチスレッドモデルのデータベース

MySQLはシングルプロセス・マルチスレッドモデルのデータベースです。接続があればスレッドプールから接続用のスレッドを割り当てるかなければ新規でスレッドを生成するようなモデルです

接続チェックの関数

Connection_handler_manager::check_and_incr_conn_countMySQLのサーバー内で、接続管理を行うコンポーネントの一部として機能する関数です。MySQLでは、クライアントからの新しい接続リクエストがサーバーに到達するたびに、接続数の管理が重要になります。この関数は、その接続数をチェックし、必要に応じて増加させる役割を担います。

実際のソースは以下

bool Connection_handler_manager::check_and_incr_conn_count(
    bool is_admin_connection) {
  bool connection_accepted = true;
  mysql_mutex_lock(&LOCK_connection_count);
  /*
    Here we allow max_connections + 1 clients to connect
    (by checking before we increment by 1).

    The last connection is reserved for SUPER users. This is
    checked later during authentication where valid_connection_count()
    is called for non-SUPER users only.
  */
  if (connection_count > max_connections && !is_admin_connection) {
    connection_accepted = false;
    m_connection_errors_max_connection++;
  } else {
    ++connection_count;

    if (connection_count > max_used_connections) {
      max_used_connections = connection_count;
      max_used_connections_time = time(nullptr);
    }
  }
  mysql_mutex_unlock(&LOCK_connection_count);
  return connection_accepted;
}

is_admin_connectionがついていればmax_connections +1まで接続ができるようになっているという。冒頭で挙げたrdsadminはRDSのマネージドな部分を実現するために接続している。すでにSUPERユーザーの接続があるのでうまく動かないよねという話。ただrdsadminはずっと接続中っぽいようにも見えていて

  1. rdsadminがコネクションをはる
  2. 一般ユーザーが大量に接続
  3. too many conn

の場合は今回のケースでは効果が出る。rdsadminも接続を貼り直したりするのでmax_connections + 1のSUPERユーザー予約枠の取り合いみたいなのを制すれば良いがそうなる前にあらかじめmax_connectionsは多めに設定しておきましょうという話だと思う。