MySQL サーバーリソースのクライアント使用を制限する方法の 1 つは、グローバル max_user_connections
システム変数をゼロ以外の値に設定することです。 これにより、任意の特定のアカウントで実行できる同時接続の数が制限されますが、一度クライアントが接続したら、実行内容には制限が課されません。 さらに、max_user_connections
を設定しても、各アカウントの管理は有効になりません。 どちらのタイプの制御も、MySQL 管理者にとって重要です。
このような問題に対処するために、MySQL では、次のサーバーリソースの使用に関する個々のアカウントの制限を許可しています:
アカウントが発行できるクエリーの数/時間
アカウントが発行できる更新の数/時間
アカウントが 1 時間ごとにサーバーに接続できる回数
アカウントによるサーバーへの同時接続の数
クライアントがクエリー制限に対してカウントを発行できるステートメント。 更新制限に対して、データベースまたはテーブルを変更するステートメントのみがカウントされます。
このコンテキストの 「account」 は、mysql.user
システムテーブルの行に対応します。 つまり、接続に適用される user
テーブル行内の User
および Host
値に対して、接続が評価されます。 たとえば、アカウント 'usera'@'%.example.com'
は、example.com
ドメイン内の任意のホストから接続することを usera
に許可するために、usera
および %.example.com
の User
および Host
値を持つ user
テーブル内の行に対応しています。 この場合、このような接続ではすべて同じアカウントが使用されるため、サーバーは、usera
による example.com
ドメイン内の任意のホストからのすべての接続に、この行のリソース制限をまとめて適用します。
MySQL 5.0 よりも前では、ユーザーの接続元である実際のホストに対して、「アカウント」が評価されていました。 この古いアカウンティング方法は、--old-style-user-limits
オプションを使用してサーバーを起動することで選択できます。 この場合、usera
が host1.example.com
と host2.example.com
から同時に接続すると、サーバーは各接続に個別にアカウントリソースの制限を適用します。 usera
が host1.example.com
から再度接続すると、サーバーはそのホストからの既存の接続とともに、その接続に対する制限を適用します。
アカウントの作成時にアカウントのリソース制限を確立するには、CREATE USER
ステートメントを使用します。 既存のアカウントの制限を変更するには、ALTER USER
を使用します。 制限される各リソースの名前を指定する WITH
句を指定します。 各制限のデフォルト値は、ゼロ (制限なし) です。 たとえば、制限された方法でのみ customer
データベースにアクセスできる新しいアカウントを作成するには、次のようなステートメントを発行します。
mysql> CREATE USER 'francis'@'localhost' IDENTIFIED BY 'frank'
-> WITH MAX_QUERIES_PER_HOUR 20
-> MAX_UPDATES_PER_HOUR 10
-> MAX_CONNECTIONS_PER_HOUR 5
-> MAX_USER_CONNECTIONS 2;
制限タイプの名前をすべて WITH
句に指定する必要はありませんが、名前を指定したものは任意の順序で表示できます。 1 時間ごとの各制限の値は、1 時間当たりの回数を表す整数にするようにしてください。 MAX_USER_CONNECTIONS
では、制限はアカウントによる同時接続の最大数を表す整数です。 この制限がゼロに設定されている場合は、グローバルな max_user_connections
システム変数の値によって同時接続の数が決定されます。 max_user_connections
もゼロである場合は、アカウントに制限がありません。
既存のアカウントの制限を変更するには、ALTER USER
ステートメントを使用します。 次のステートメントは、francis
に対するクエリー制限を 100 に変更します。
mysql> ALTER USER 'francis'@'localhost' WITH MAX_QUERIES_PER_HOUR 100;
このステートメントは、指定された制限値のみを変更し、それ以外のアカウントは未変更のままにします。
制限を削除するには、その値をゼロに設定します。 たとえば、francis
が接続できる 1 時間当たりの回数に対する制限を削除するには、次のステートメントを使用します。
mysql> ALTER USER 'francis'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 0;
すでに説明したように、アカウントに対する同時接続の制限は、MAX_USER_CONNECTIONS
制限および max_user_connections
システム変数によって決定されます。 グローバル max_user_connections
値が 10 で、3 つのアカウントに次のように個別のリソース制限が指定されているとします:
ALTER USER 'user1'@'localhost' WITH MAX_USER_CONNECTIONS 0;
ALTER USER 'user2'@'localhost' WITH MAX_USER_CONNECTIONS 5;
ALTER USER 'user3'@'localhost' WITH MAX_USER_CONNECTIONS 20;
user1
の接続制限は、MAX_USER_CONNECTIONS
制限がゼロであるため、10 (グローバル max_user_connections
値) です。user2
および user3
には、ゼロ以外の MAX_USER_CONNECTIONS
制限があるため、それぞれ接続制限は 5 および 20 です。
サーバーはアカウントに対応する user
テーブル行に、アカウントに対するリソース制限を格納します。 max_questions
、max_updates
、または max_connections
カラムには、1 時間当たりの制限が格納され、max_user_connections
カラムには、MAX_USER_CONNECTIONS
の制限が格納されます。 (セクション6.2.3「付与テーブル」を参照してください。)
任意のアカウントによるリソースのいずれかの使用に対してゼロ以外の制限が設定されている場合は、リソース使用のカウントが発生します。
サーバーが実行されると、各アカウントがリソースを使用する回数がカウントされます。 アカウントが過去 1 時間以内の接続数の制限に達した場合、サーバーはその時間が稼働するまでアカウントのそれ以上の接続を拒否します。 同様に、アカウントがクエリーまたは更新の数の制限に達した場合、サーバーは時間が稼働するまでそれ以上のクエリーまたは更新を拒否します。 このような場合、サーバーは適切なエラーメッセージを発行します。
リソースカウントは、クライアントごとではなく、アカウントごとに行われます。 たとえば、アカウントのクエリー制限が 50 である場合は、サーバーへの 2 つの同時クライアント接続を作成しても、制限を 100 に増加できません。 両方の接続で発行されたクエリーは、まとめてカウントされます。
現在の 1 時間ごとのリソース使用のカウントは、すべてのアカウントに対してグローバルにリセットすることも、特定のアカウントごとに個別にリセットすることもできます。
すべてのアカウントに対して現在のカウントをゼロにリセットするには、
FLUSH USER_RESOURCES
ステートメント発行します。 また、(たとえば、FLUSH PRIVILEGES
ステートメントまたは mysqladmin reload コマンドを使用して) 付与テーブルを再ロードして、カウントをリセットすることもできます。個々のアカウントのカウントは、制限のいずれかを再度設定することでゼロにリセットできます。 アカウントに現在割り当てられている値と等しい制限値を指定します。
時間ごとのカウンタのリセットは、MAX_USER_CONNECTIONS
の制限には影響しません。
すべてのカウントは、サーバーの起動時にゼロから始まります。 カウントはサーバーの再起動を引き継ぎません。
MAX_USER_CONNECTIONS
の制限では、アカウントが許可されている接続の最大数を現在開いている場合に、エッジケースが発生する可能性があります。接続が発生する時点までにサーバーで切断が完全に処理されていない場合に、切断後にすぐに接続すると、エラー (ER_TOO_MANY_USER_CONNECTIONS
または ER_USER_LIMIT_REACHED
) が発生する可能性があります。 サーバーが切断処理を終了すると、別の接続が許可されます。