データベースにアクセスするときに必要なコネクションを確立するためにはある程度の時間がかかります。そこで、一度確立したコネクションは解放せずに一定数プールしておいて次回のアクセス時に使い回すことを考えます。このコネクションプールという仕組みをクライアント側で実装することで、コネクションをプールしておくためのメモリなどは別途必要にはなりますが、アクセスのためのコネクション確立処理が不要になるため、確立処理に時間がかかる場合には全体として処理が高速化されます。
Rails の config/database.yml には pool という設定値があります。これによって、データベースのクライアントである Rails のコネクションプールの最大値を設定できます。例えば pool を 5 に設定するとデータベースにアクセスが必要なリクエストを並列して最大で 5 つ同時に処理できます。ただし 5 を越えるリクエストがなされると、越えた分のリクエストは 5 つのコネクションを利用したリクエスト処理が完了するまで待たされることになります。そして、config/database.yml の設定値 timeout ミリセカンド経過してもコネクションが得られないリクエストはタイムアウトエラーになります。データベースへのアクセスが必要なリクエストを大量に同時処理しなければならない Rails アプリケーションの場合は pool または timeout の値を上げることで対応します。
確立されたコネクションは MySQL の場合、SHOW PROCESSLIST によってスレッドとして確認できます。サーバ側ではコネクションが増加するとメモリなどのリソースが消費されるため、/etc/my.cnf などで max_connections によって上限を設定します。現在の設定値は以下のコマンドで確認できます。
mysql> SHOW GLOBAL VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set (0.00 sec)
そのうち、実際に現在使用されているコネクション数などは以下のコマンドで確認します。自分以外は誰も接続していないようです。
mysql> SHOW GLOBAL STATUS LIKE 'threads_%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 7 | ←使い回すためにMySQL側でキャッシュされているスレッド (クライアント側の pool と区別)
| Threads_connected | 1 | ←現在の接続されているスレッド数
| Threads_created | 809 | ←新しいスレッドが作成される度に増加 (cached 値が小さいと作っては壊すためすぐ増加)
| Threads_running | 1 | ←スリープ状態でないスレッド数
+-------------------+-------+
4 rows in set (0.00 sec)
スレッドのキャッシュ数の上限値設定は以下のコマンドで確認できます。
mysql> SHOW GLOBAL VARIABLES LIKE 'thread_cache_size';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| thread_cache_size | 9 |
+-------------------+-------+
1 row in set (0.00 sec)
各コネクションのステータスなどの情報を詳細に確認したい場合は更に以下のコマンドを実行します。Info に "show processlist" とあります。確かに自分のプロセスのようです。
mysql> SHOW PROCESSLIST;
+-------+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+------+-----------+------+---------+------+-------+------------------+
| 81276 | root | localhost | NULL | Query | 0 | init | show processlist |
+-------+------+-----------+------+---------+------+-------+------------------+
1 row in set (0.00 sec)
ちなみに、過去の最大同時接続数は以下のようにして確認します。
mysql> SHOW GLOBAL STATUS LIKE 'max_used_connections';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| Max_used_connections | 8 |
+----------------------+-------+
1 row in set (0.00 sec)
あまり参考にならない情報かもしれませんが、累計で作成されたコネクション数は以下のように確認できます。作成された累計スレッド数 Threads_created
と区別してください。
mysql> SHOW GLOBAL STATUS LIKE 'connections';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Connections | 81335 |
+---------------+-------+
1 row in set (0.00 sec)
InnoDB にはバッファプールという概念があります。名称は似ていますが、クライアント側の仕組みであるコネクションプールとは無関係です。現在の設定値は以下のコマンドで確認できます。
mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
1 row in set (0.00 sec)
134217728 バイト (128 MB) であることが分かりました。これだけのメモリ領域が InnoDB のキャッシュとして利用できるということになります。サイズが大きければ大きいほど、ディスクアクセスの回数を低減させることができるため、処理が高速になります。ただし、あくまでもキャッシュですので不足していることによって事故が発生することはありません。