Amazon Web Services ブログ

Amazon RDS for MySQL のパラメーターを設定するためのベストプラクティス。パート 3: セキュリティ、操作管理性、および接続タイムアウトに関連するパラメーター

このシリーズの前回のブログ投稿では、Amazon RDS for MySQL でレプリケーションを最適化するために使用する MySQL パラメータと、それらに関連するベストプラクティスについて説明しました。本日の記事では、RDS MySQL 環境でさまざまなセキュリティ機能を実装するために最も重要で一般的に使用されている MySQL パラメータについて説明します。また、RDS DB インスタンスの操作管理と問題のトラブルシューティングに役立つパラメータについても説明します。さらに、照合順序と文字セットに関連するいくつかの便利なパラメータについても説明します。

セキュリティに関連するパラメータ

今から、セキュリティ関連の各パラメータを設定するベストプラクティスをご紹介します。

init_connect

このパラメータは、接続する各クライアントに対して実行するサーバーの文字列を定義します。このパラメータにはデフォルト値はありません。文字列は、セミコロンで区切られた 1 つ以上の SQL 文で構成されています。

たとえば、このパラメータを使用して、どのデータベースユーザーがデータベースに正常に接続したかの簡単な監査を作成できます。そのためには、まず監査テーブルとトリガーを作成します。その後、init_connect 値をトリガー名に設定します。設定したら、クライアントがパラメータを接続するたびに、接続の詳細が監査テーブルに書き込まれます。

次の例のように、このパラメータを使用して特定のユーザーアカウントの自動コミットを無効にすることもできます。

init_connect = 'set autocommit=case current_user() when 'test@localhost' then 0 else 1 end’. 

old_passwords

このパラメータは、PASSWORD 関数で使用するパスワードハッシュ方式を制御します。また、IDENTIFIED BY 句を使用してパスワードを指定する CREATE USER ステートメントおよび GRANT ステートメントによって実行されるパスワードハッシュにも影響します。

このパラメータを有効にしないことを強くお勧めします。有効にした場合、PASSWORD 関数は安全でないパスワードハッシュを使用してしまうからです。このパラメータのデフォルト値は 0 で、これは MySQL バージョン 4.1 のネイティブハッシュを使用します。

default_password_lifetime

このパラメータは、MySQL バージョン 5.7 から利用可能です。これは、グローバル自動パスワード有効期限ポリシーを定義するために使用します。値が N に設定されている場合、パスワードの有効期限は N 日であり、各パスワードは N 日ごとに変更する必要があります。デフォルト値は 0 で、これは自動パスワード有効期限を無効にします。許容値は、0 から 65,535 の範囲です。

セキュリティ規格の要件とパスワードポリシーを満たすようにこのパラメータを設定します。CREATE USER または ALTER USER を使用して、たとえば次のように、アカウントの値を明示的に設定することもできます。これは、デフォルトのパラメータ設定をオーバーライドします。

mysql> ALTER USER ‘test’@‘localhost' PASSWORD EXPIRE INTERVAL 30 DAY;

max_user_connections

このパラメータを使用して、ゼロ以外の値に設定することで、クライアントの MySQL サーバーリソースの使用を制限できます。このパラメータは、指定されたアカウントが確立できる同時接続数を制限します。接続数がこの値に達したときに、新しい接続を作成しようとすると、「警告: mysql_connect (): ユーザー xxxxxxxx は既に ‘max_user_connections’ 個以上のアクティブ接続を持っています」のようなエラーを受け取ります。デフォルト値は 0 です。これは、指定されたアカウントの同時接続を制限しません。

操作管理に関するパラメータ

今から、操作管理に関連する各パラメータを設定するベストプラクティスをご紹介します。

log_warnings

新規接続の試行について中止された接続およびアクセス拒否エラーをログに記録するには、log_warnings の値を 1 より大きい値に設定します。通常、接続に関連する問題をデバッグし、MySQL エラーログにデータを収集するために 2 に設定します。デフォルト値は 1 です。

このパラメータは、切断やその他の軽微な問題に関する警告をエラーログに記録します。詳細については、MySQL ドキュメントの AWS サポート記事「MySQL を実行している Amazon RDS インスタンスにログインできなかった試行をログに記録する方法」および「サーバーシステム変数」を参照してください。

performance_schema

このパラメータは、パフォーマンススキーマを有効または無効にするために使用します。このパラメータは、0 (パフォーマンススキーマを無効にする) または 1 (パフォーマンススキーマを有効にする) のどちらかの値にのみ設定することができます。MySQL 5.6 では、このパラメータのデフォルト値は 1 で、これによりパフォーマンススキーマが有効になります。5.7 では、このパラメータのデフォルト値は 0 です。これはパフォーマンススキーマを無効にします。パフォーマンススキーマを使用するかどうかに応じてこのパラメータを設定します。

Event_scheduler

このよく使用されるパラメータにより、イベントスケジューラをオンまたはオフにします。デフォルト値は OFF で、使用可能な値は ON または OFF です。値 OFF はイベントスケジューラを停止し、ON はイベントスケジューラを起動します。

このパラメータの値をどのように設定するかは、使用要件によって異なります。ただし、イベントスケジューラには、イベントの複数同時実行に対する保護はありません。たとえば、2 分ごとに実行されるようにスケジュールされているイベントが 2 分以上かかるとします。次にスケジュールされているイベントによって、イベントの実行が滞ることがあります。このようなパイルアップはデッドロックを引き起こす可能性があります。これを回避するためのベストプラクティスは、スレッド間の通信に GET_LOCK 関数を使用することです。

以下は、これを行う方法を示した例です。

CREATE EVENT test_event ON SCHEDULE EVERY 10 SECOND DO
BEGIN
 DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
 BEGIN
   DO RELEASE_LOCK('test_event');
 END;
 IF GET_LOCK('testlock_event', 0) THEN
   -- add some   logic/DML operation here as per your requirement :
  END IF;
  DO RELEASE_LOCK('testlock_event');
END;

次のように、情報スキーマにイベント情報をクエリすることもできます。

> select * from information_schema.EVENTS\G 

イベントに関連する問題をトラブルシューティングする必要がある場合は、エラーログに通常役立つ情報が含まれています。現在のイベントスレッドステータスを表示するには、コマンド show full processlist を使用します。詳細については、MySQL ドキュメントの「イベントスケジューラのスレッド状態」を参照してください。

複製シナリオでは、マスターとレプリカの両方でイベントスケジューラを有効にすると、誤った結果が生じる可能性があります。そのような結果は、マスタ上のイベントが目的のレコードを生成し、そのレコードがレプリカに複製されるために発生します。レプリカでイベントスケジューラを有効にすると、イベントが再度実行されます。通常のレプリケーションでは、プロセスはイベントに対する変更 (CREATEALTERDROP など) をレプリカにレプリケートするため、マスターとレプリカのイベント設定は同じです。そのため、イベントステータスは SLAVESIDE_DISABLED にして、レプリカが昇格しない限り、レプリカ上のイベントは有効にならないようにします。

レプリカをマスターに昇格させた後、新しいマスターからイベントの実行を開始するには、次の手順を実行します。

  • イベントスケジューラを無効にします (有効になっている場合)。
  • 以下にリストされている更新ステートメントを使用して、元のマスターからのすべての複製イベントの状況を ENABLED に設定します。
  • イベントスケジューラをオンにします。

どのイベントのステータスが SLAVESIDE_DISABLED であるかを確認するには、次のクエリを使用します。

SELECT EVENT_SCHEMA, EVENT_NAME
  FROM INFORMATION_SCHEMA.EVENTS
  WHERE STATUS = 'SLAVESIDE_DISABLED';

すべてのイベントの状況を使用可能として更新するには、以下のステートメントを使用します。

UPDATE mysql.event SET status='ENABLED';

RDS レプリカに複数のマスター (外部マスターなど) がある場合は、以下に示すように、発信者列を使用して特定のマスターからのイベントを有効にできます。

UPDATE mysql.event SET status='ENABLED' WHERE originator=817021841; 

ここで、817021841 は発信元マスターのサーバー ID です。この ID は SELECT @@ server_id を使って見つけることができます。

explicit_defaults_for_timestamp

このパラメータは、MySQL が TIMESTAMP データ型の列のデフォルト値および NULL 値に対してどのように動作するかを決定します。デフォルト値は 1 で、これはパラメータを有効にし、許容値は 0 と 1 です。

NULL 値とデフォルト値を持つ TIMESTAMP 列の非標準の動作を避けるために、この値を有効にしておくことをお勧めします。詳細については、「MySQL 5.6 ドキュメント」および「MySQL 5.7 ドキュメント」を参照してください。このパラメータを有効にすると、MySQL 5.6 ドキュメントおよび MySQL 5.7 ドキュメントで説明されているように、サーバーは非標準の動作を無効にします。

ただし、このパラメータが有効になっていると、次のようなエラーが発生する可能性があります。

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'column_name' cannot be null' error when not specifying a value. 

これらは、RDS MySQL では explicit_defaults_for_timestamp パラメータのデフォルト値が 1 (有効) になっているために発生します。この設定は、MySQL のデフォルトの 0 (無効) とは異なります。値が明示的に指定されていない場合、この矛盾によって列のデフォルト設定はなくなります。このエラーを回避するには、パラメータグループを変更して explicit_defaults_for_timestamp の値を 0 に設定します。このパラメータは静的なので、変更には再起動が必要です。

ただし、explicit_defaults_for_timestamp は、将来の MySQL リリースで削除される予定の MySQL TIMESTAMP 列の非標準の動作を制御することのみを目的としているため、非推奨です。MySQL ドキュメントによると、これらの非標準の動作が削除されると、このパラメータも使用されなくなり、削除されます。したがって、現在のタイムスタンプ値を設定するために TIMESTAMP 列の値を完全に指定するようにコードを変更することを計画することをお勧めします。CURRENT_TIMESTAMP や、NOW () のような同義語を使用できます。

文字セットに関連するパラメータ

文字セットは、通常、照合の種類から派生したシンボルとエンコードのセットです。文字セットを使用して、文字をビットにエンコードします。照合と文字セットは、インスタンスレベル、データベースレベル、テーブルレベル、または列レベルで設定できます。RDS MySQL はデフォルトでデータベースに Latin1 エンコーディングを使用します。使用されている文字セットの詳細については、MySQL ドキュメントの information_schema.CHARACTER_SETS テーブルを参照してください。

以下は、RDS MySQL の文字セットに関連して利用できるパラメータです。

パラメータ名 説明 デフォルト値 利用可能な値
character_set_client クライアントから到着するステートメントの文字セット utf8 big5, dec8, cp850, hp8, koi8r, latin1, latin2, swe7, ascii, ujis, sjis, hebrew, tis620, euckr, koi8u, gb2312, greek, cp1250, gbk, latin5, armscii8, utf8, cp866, keybcs2, macce, macroman, cp852, latin7, utf8mb4, cp1251, cp1256, cp1257, binary, geostd8, cp932, eucjpms
character_set_connection 文字セットイントロデューサーを持たないリテラル、および数値から文字列への変換に使用される文字セット

utf8

 

big5, dec8, cp850, hp8, koi8r, latin1, latin2, swe7, ascii, ujis, sjis, hebrew, tis620, euckr, koi8u, gb2312, greek, cp1250, gbk, latin5, armscii8, utf8, ucs2, cp866, keybcs2, macce, macroman, cp852, latin7, utf8mb4, cp1251, utf16, cp1256, cp1257, utf32, binary, geostd8, cp932, eucjpms
character_set_database デフォルトデータベースで使用される文字セット latin1 big5, dec8, cp850, hp8, koi8r, latin1, latin2, swe7, ascii, ujis, sjis, hebrew, tis620, euckr, koi8u, gb2312, greek, cp1250, gbk, latin5, armscii8, utf8, ucs2, cp866, keybcs2, macce, macroman, cp852, latin7, utf8mb4, cp1251, utf16, cp1256, cp1257, utf32, binary, geostd8, cp932, eucjpms
character_set_filesystem ファイルシステムの文字セット binary big5, dec8, cp850, hp8, koi8r, latin1, latin2, swe7, ascii, ujis, sjis, hebrew, tis620, euckr, koi8u, gb2312, greek, cp1250, gbk, latin5, armscii8, utf8, ucs2, cp866, keybcs2, macce, macroman, cp852, latin7, utf8mb4, cp1251, utf16, cp1256, cp1257, utf32, binary, geostd8, cp932, eucjpms
 character_set_results クライアントにクエリ結果を返すために使用する文字セット utf8 big5, dec8, cp850, hp8, koi8r, latin1, latin2, swe7, ascii, ujis, sjis, hebrew, tis620, euckr, koi8u, gb2312, greek, cp1250, gbk, latin5, armscii8, utf8, ucs2, cp866, keybcs2, macce, macroman, cp852, latin7, utf8mb4, cp1251, utf16, cp1256, cp1257, utf32, binary, geostd8, cp932, eucjpms
character_set_server サーバーのデフォルトの文字セット latin1 big5, dec8, cp850, hp8, koi8r, latin1, latin2, swe7, ascii, ujis, sjis, hebrew, tis620, euckr, koi8u, gb2312, greek, cp1250, gbk, latin5, armscii8, utf8, ucs2, cp866, keybcs2, macce, macroman, cp852, latin7, utf8mb4, cp1251, utf16, cp1256, cp1257, utf32, binary, geostd8, cp932, eucjpms

列固有の文字セットは、テーブルレベルでデフォルトの文字セットを上書きします。同様に、テーブル固有の文字セットは、データベースレベルでデフォルトの文字セットを上書きします。また、データベース固有の文字セットは、インスタンスレベルでデフォルトの文字セットを上書きします。

インスタンスレベルで文字セットパラメータを確認するには、次のクエリを使用します。

MySQL [(none)]> show variables like '%character%';
+--------------------------+------------------------------------------------+
| Variable_name            | Value                                          |
+--------------------------+------------------------------------------------+
| character_set_client     | utf8                                           |
| character_set_connection | utf8                                           |
| character_set_database   | latin1                                         |
| character_set_filesystem | binary                                         |
| character_set_results    | utf8                                           |
| character_set_server     | latin1                                         |
| character_set_system     | utf8                                           |
| character_sets_dir       | /rdsdbbin/oscar-5.6.10a.31.101/share/charsets/ |
+--------------------------+------------------------------------------------+
8 rows in set (0.00 sec)

特定のデータベースのデフォルトの文字セットを確認するには、次のようなクエリを使用します。この例ではデータベース名「TEST」を使用しています。

MySQL [(none)]> SELECT SCHEMA_NAME,
    -> DEFAULT_CHARACTER_SET_NAME
    -> FROM INFORMATION_SCHEMA.SCHEMATA
    -> WHERE SCHEMA_NAME='TEST';
+-------------+----------------------------+
| SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME |
+-------------+----------------------------+
| TEST        | utf8                       |
+-------------+----------------------------+
1 row in set (0.00 sec)

テーブルレベルと列レベルの文字セットを確認するには、コマンド show create table <table_name> を使用できます。

インスタンスレベルでパラメータを変更するには、パラメータグループに値を設定します。これを行うには、次の手順に従います。

  1. カスタムパラメータグループを作成します。
  2. パラメータを必要な値に変更します。
  3. 次のコマンドを使用してデータベースにログインし、パラメータの値を表示します。
> show variables like '%character%';

インスタンスがすでにカスタムパラメータグループを使用している場合は、そこでパラメータを変更できます。詳細については、RDS ドキュメントの「DB パラメータグループを使用する」を参照してください。

ただし、> show variables like '%character%'; を使用してクエリを行った場合、パラメータ character_set_clientcharacter_set_connection、および character_set_results は、パラメータグループに示されている文字セットを取りません。MySQL ドキュメントで説明されているように、「これらの変数のセッション値は、クライアントがサーバーに接続するときにクライアントから要求された文字セットを使用して設定されます」。 つまり、各接続中に文字セットを明示的に指定する必要があります。

これを行うには、SET NAMES ステートメントを用いてセッションレベルのパラメータを使用します。SQL ステートメント SET NAMES 'char_set_name' は、次の 3 つの SQL ステートメントと同じです。

> set character_set_client = char_set_name;
> set character_set_connection = char_set_name;
> set character_set_results = char_set_name;

たとえば、以下に示すように、SQL ステートメント SET NAMES utf8mb4 を使用して、すべての必要なパラメータ (character_set_clientcharacter_set_connectioncharacter_set_results) を utf8mb4 に設定できます。

MySQL [(none)]> SET NAMES utf8mb4
    -> ;
Query OK, 0 rows affected (0.02 sec)
MySQL [(none)]>  show variables like '%character%';
+--------------------------+------------------------------------------------+
| Variable_name            | Value                                          |
+--------------------------+------------------------------------------------+
| character_set_client     | utf8mb4                                        |
| character_set_connection | utf8mb4                                        |
| character_set_database   | latin1                                         |
| character_set_filesystem | binary                                         |
| character_set_results    | utf8mb4                                        |
| character_set_server     | latin1                                         |
| character_set_system     | utf8                                           |
| character_sets_dir       | /rdsdbbin/oscar-5.6.10a.31.101/share/charsets/ |
+--------------------------+------------------------------------------------+
8 rows in set (0.00 sec)

アプリケーションからの接続ごとに SET NAMES コマンドを実行しないようにするには、init_connect パラメータを使用できます。以下は、init_connect を使用してこれらのパラメータの値を utf8mb4 に設定した例です。

-- setting the 'init_connect' to 'SET NAMES utf8mb4' via parameter group
mysql> show variables like '%init_connect%'; +---------------+-------------------+ 
| Variable_name | Value             | 
+---------------+-------------------+ 
| init_connect  | SET NAMES utf8mb4 | 
+---------------+-------------------+

あるいは、MySQL ドキュメントに記載されているように、次のようにパラメータグループ内の以下のパラメータを変更できます。これらの設定はクライアント情報を無視し、デフォルトのサーバー文字セットを使用します。

character-set-client-handshake=0 
skip-character-set-client-handshake=1

文字セットパラメータを変更しても、既存のテーブルの文字セットは変更されません。ただし、パラメータ変更後に作成されたすべてのテーブルには、新しい文字セットがあります。既存のテーブルの文字セットを変更するには、ALTER TABLE ステートメントを使用する必要があります。たとえば、

ALTER TABLE <table_name>
CHARACTER SET <desired_character_set>;

同様に、データベース固有および列固有の設定を変更するには、以下に示すように ALTER DATABASE および ALTER TABLE ステートメントを使用します。

ALTER DATABASE <database_name> CHARACTER SET = utf8mb4  ;
ALTER TABLE <table_name> CHANGE column_name <column_name> <datatype> CHARACTER SET <desired_character_set>;

MySQL の utf8 文字セットは 1 文字あたり最大 3 バイトを使用しますが、utf8mb4 文字セットは 1 文字あたり 4 バイトを使用します。utf8 文字セットには、中国語、日本語、韓国語の文字など、さまざまな多言語文字を格納できます。ただし、格納できない特定の文字があります。たとえば、Unicode 文字の雪だるま (U + 2603) ☃ などのさまざまな絵文字は、utf 8 に格納できませんが、utf 8mb 4 には格納できます。utf8mb4 は utf8 文字セットの文字をすべて格納できるため、utf8mb4 を使用することをお勧めします。

照合順序に関連するパラメータ

照合は、文字セットの文字を比較するための一連の規則を定義します。各文字セットには 1 つ以上の照合順序があり、少なくとも 1 つのデフォルトの照合順序があります。

SHOW CHARACTER SET コマンドを使用して、特定の文字セットのデフォルトの照合順序を取得できます。MySQL ドキュメントのテーブル information_schema.collations にもデフォルトの照合順序があります。

各照合名には 4 つの部分があります。順番に、これらは次のとおりです。

  1. 文字セット名
  2. たとえば ja なら日本語など、それはどの言語に関するものか。特別な「言語」はバイナリです。つまり、各バイトは 1 つずつ直接比較されます。
  3. それが UCA 9.0.0 ベースの照合であるか。UCA 9.0.0 ベースの照合名には 0900 が含まれます
  4. アクセント記号があるかどうか、大文字と小文字が区別されるかどうか、またはその両方に応じて、最大 3 つの修飾子。

たとえば、照合 utf8mb4_ja_0900_as_cs では、サポートしている文字セットは utf8mb4 であること、言語は日本語であること、900 は UCA 9.0.0 ベースの照合に基づいていること、そして cs は大文字と小文字を区別することを意味します。全部で 5 つのアクセントとケース修飾子があります

  • ai: アクセントを区別せず、ä は a と等しい。
  • as: アクセントを区別し、ä は a と等しくない。
  • ci: 大文字と小文字を区別せず、a は A と等しい。
  • cs: 大文字と小文字が区別し、a は A と等しくない。
  • ks: かなを区別する (日本語のみ)。

以下は RDS MySQL の照合に関連して利用できるパラメータです。

パラメータ 説明 デフォルト値
collation_connection 接続文字セットの照合 utf8_general_ci
collation_server サーバーのデフォルト照合 latin1_swedish_ci

文字セットと同様に、インスタンス、データベース、テーブル、および列の各レベルで照合順序を設定できます。列固有の照合順序は、テーブルレベルでデフォルトの照合順序を上書きします。同様に、テーブル固有の照合順序は、データベースレベルでデフォルトの照合順序を上書きします。また、データベース固有の照合順序は、インスタンスレベルでデフォルトの照合順序を上書きします。

インスタンスレベルで照合パラメータを確認するには、次のクエリを使用できます。

MySQL [(none)]> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+

特定のデータベースのデフォルトの照合順序を確認するには、次のクエリを使用できます。In this example, the database name is test.

MySQL [(none)]> SELECT SCHEMA_NAME,
    -> DEFAULT_COLLATION_NAME
    -> FROM INFORMATION_SCHEMA.SCHEMATA
    -> WHERE SCHEMA_NAME = 'test';
+-------------+------------------------+
| SCHEMA_NAME | DEFAULT_COLLATION_NAME |
+-------------+------------------------+
| test        | utf8_general_ci        |
+-------------+------------------------+
1 row in set (0.00 sec)

テーブルレベルと列レベルの照合値を確認するには、show create table <table_name> を使用できます。

インスタンスレベルでパラメータを変更するには、パラメータグループに値を設定します。これを行うには、次の手順に従います。

  1. カスタムパラメータグループを作成します。
  2. パラメータを必要な値に変更します。
  3. 次のコマンドを使用してデータベースにログインし、パラメータの値を確認します。
> show variables like ‘%collation%’;

インスタンスがすでにカスタムパラメータグループを使用している場合は、そこでパラメータを変更できます。詳細については、RDS ドキュメントの「DB パラメータグループを使用する」を参照してください。

照合パラメータを変更しても、既存のテーブルの照合順序は変更されません。ただし、パラメータ変更後に作成されたすべてのテーブルに新しい照合順序が備わります。既存のテーブルの照合順序を変更するには、ALTER TABLE ステートメントを使用する必要があります。例えば、

ALTER TABLE <table_name> COLLATE  <desired_collation>;

同様に、データベース固有および列固有の設定を変更するには、以下に示すように ALTER DATABASE および ALTER TABLE ステートメントを使用します。

ALTER DATABASE <database_name>  COLLATE  <desired_collation> ;
ALTER TABLE <table_name> CHANGE column_name <column_name> <datatype> COLLATE  <desired_collation>;

slow_query_log

このパラメータは、スロークエリを識別するのに非常に役立ちます。スロークエリログを無効にするには 0 (または OFF)、ログを有効にするには 1 (または ON) に設定します。デフォルト値は 0 であり、この機能を無効にします。

クエリが遅いかどうかを判断するためのしきい値は、別のパラメータ long_query_time によって定義されます。long_query_time パラメータは、クエリの実行時間を秒単位で定義します。テーブルまたはファイルのどちらでもスロークエリをキャプチャできます。どちらを実行するかは、別のパラメータ log_output の値によって異なり、TABLE または FILE と等しくなる可能性があります。デフォルトはテーブルです。詳細については、こちらの YouTube ビデオをご覧ください。

log_queries_not_using_indexes

これは、問題のあるクエリを識別するためによく使用される別の 1 のパラメータです。このパラメータを 1 (有効) に設定すると、インデックスを使用していないすべてのクエリがスロークエリログに記録されます。デフォルトでは、このパラメータは無効になっており、値は 0 です。

innodb_file_per_table

innodb_file_per_table が有効な場合 (デフォルト値の 1 に値を設定することで)、InnoDB はシステムテーブルスペースではなく個別の .ibd ファイルに作成された各テーブルのデータとインデックスを保存します。デフォルトでは、RDS はこのパラメータを有効にします。つまり、各テーブルスペースのデータはそれぞれの .ibd ファイルに格納されます。innodb_file_per_table を 0 に設定して無効にすると、すべてのテーブルもシステムテーブルスペースに割り当てられます。その場合、システムテーブルスペースに割り当てられているテーブルからテーブルまたは索引を削除するか、データを削除または切り捨てると、以前に使用していた領域が再利用可能としてマークされます。ただし、このコマンドでファイルシステムの空き容量は増えません。

このような場合は、innodb_file_per_table を 1 に設定して、個々の InnoDB テーブルを削除し、それらのテーブルで使用している DB インスタンスのストレージを再利用できるようにすることをお勧めします。ほとんどの場合、innodb_file_per_table パラメータを 1 に設定することがベストプラクティスです。

ただし、データベース内のテーブル数が非常に多い場合は、別の方法をとることをお勧めします。たとえば、標準 (磁気) または汎用 SSD ストレージを使用する場合は 1,000 テーブル以上、プロビジョンド IOPS ストレージを使用する場合は 10,000 テーブル以上の場合です。この場合、データベースクラッシュの回復にかかる時間を短縮するために、この値を 0 に設定する必要があります。このように改善されるのは、このパラメータを 0 に設定すると、個々のテーブルスペースが作成されないためです。

接続タイムアウトに関連するパラメータ

以下は、接続タイムアウトに関連するいくつかのパラメータです。これらのパラメータは、MySQL エラーログのタイムアウト関連のエラーを排除するために調整する必要があります。

net_write_timeout

このパラメータは、書き込みを中止する前に、ブロックが接続に書き込まれるのを待つ秒数を示します。推奨値は 120 秒です。これは要件に合わせて調整する必要があるかもしれません (デフォルトは 60 秒です)。通常、エラーログの「Got timeout」メッセージは mysqld に設定された値によってトリガーされ、エラーログの「Got an error」メッセージは異常終了した接続によってトリガーされます。

max_allowed_packet

このパラメータは、1 パケットの最大サイズ、生成されたストリング、または中間ストリング、あるいは mysql_stmt_send_long_data () C API 関数が送信した任意のパラメータを示します。デフォルト設定は 4 MB です。64 MB の値をお勧めします。必要に応じてパラメータを調整する必要があります。クライアントの max_allowed_packet 値よりも多くのデータがある行がある場合、エラーが報告されます。大きな BLOB 列または長い文字列を使用している場合は、この値を増やす必要があります。使用したい最大の BLOB と同じ大きさの値に設定してください。max_allowed_packet のプロトコル制限は 1 GB です。

wait_timeout

このパラメータは、サーバーが非対話型接続を閉じる前にその活動を待機する秒数を示します (非対話型タイムアウト)。デフォルト値は 28,800 です。クライアントが wait_timeout 秒間何もしていない場合、MySQL サーバーは接続を終了します。この変数の適切な設定は特定の環境によって異なります。

wait_timeout が小さいと、大規模なトランザクション (たとえば、大規模な行ベースの一括更新、挿入、削除) を再生し、その再生に wait_timeout より長い時間がかかる場合に、RDS のポイントインタイムリストアをが中断される可能性があります。この問題を回避するには、wait_time を 600 (10 分) 以上に設定します。wait_timeout の値は、実際に他の「バッドプラクティス」が働いているときにだけ要因になるでしょう。たとえば、InnoDB テーブルに固有のキーを含めないと、行ベースのログ一括更新は、最初にソースインスタンスで実行した場合よりも再生に時間がかかります。

interactive_timeout

MySQL のマニュアルによると、このパラメータは、サーバーが対話型接続を閉じる前にその接続を監視する秒数です。デフォルト値は 28,800 です。対話型クライアントは、CLIENT_INTERACTIVE オプションを使用して mysql_real_connect () を実行するクライアントとして定義されています。このパラメータの場合、適切な設定は特定の環境によって異なります。エラーが発生した場合は、エラーがなくなるまで値を徐々に増やす必要があります。

skip_name_resolve

このパラメータは、--skip-name-resolve オプションの値から設定されます。OFF (RDS の場合は 0) の場合、mysqld はクライアント接続をチェックするときにホスト名を解決します。ON の場合 (RDS の場合は 1)、mysqld は IP 番号のみを使用します。この場合、許可テーブル内のすべての Host 列の値は IP アドレスまたは localhost でなければなりません。したがって、このパラメータは接続時の DNS ルックアップを回避するために使用します。デフォルトではオフ (0 に設定) になっています。

このパラメータをオフにすると、エラーログに次のような警告が記録されることがあります。

2017-03-03 13:10:00          [-]2017-03-03 13:07:22 3396 [Warning] IP address ‘<ip-address-rep-instance>’ could not be resolved: Temporary failure in name resolution                

innodb_print_all_deadlocks

このパラメータを有効にすると (1 に設定)、InnoDB ユーザートランザクションに関連するデッドロックが MySQL エラーログに記録されます。それ以外の場合、この情報は SHOW ENGINE INNODB STATUS コマンドを使用して最後のデッドロックについてのみ利用できます。このオプションを使用すると、アプリケーションロジックにデッドロックを検出して操作を再試行するための適切なエラー処理がない理由をトラブルシューティングできます。デフォルトでは、このパラメータは無効、つまり 0 に設定されています。

max_connections

このパラメータは、MySQL が許可する最大同時接続数を制限するために使用します。利用可能な接続がこれ以上ない場合は、接続が試行されると次のエラーが返されます。

ERROR 1040 (HY000): Too many connections

max_connections の現在の値は、次のコマンドを使用して見つけることができます。

mysql> SHOW GLOBAL VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 500   |
+-----------------+-------+
1 row in set (0.00 sec)

mysql> SELECT * FROM information_schema.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'max_connections';
+-----------------+----------------+
| VARIABLE_NAME   | VARIABLE_VALUE |
+-----------------+----------------+
| MAX_CONNECTIONS | 500            |
+-----------------+----------------+
1 row in set (0.00 sec)

デフォルトでは、このパラメータは DBInstanceClassMemory の値から計算される式に基づいています。 このパラメータは、RDS インスタンスの使用可能な合計メモリーに基づいて自動的に調整されます。式は次のとおりです。

max_connections = DBInstanceClassMemory/12582880

これらの値を変更することはお勧めできません。もっと接続が必要な場合は、もっと大きい RDS インスタンスサイズにアップグレードすることをお勧めします。

許可する接続数を決定して max_used_connection の最適値を調整するときは、max_used_connections ステータス値を監視することをお勧めします。max_used_connections サーバー状況変数は、サーバーの始動以降に同時に使用されていた最大接続数を報告します。次のコマンドで値を確認します。

mysql> show global status like '%Conn%';

max_connect_errors

このパラメータは、サーバーがホストをブロックするまでに発生する可能性がある接続エラーの数を示します。ホストからの max_connect_errors を超える連続した接続要求が、正常な接続なしで中断された場合、サーバーはそのホストからそれ以降の接続をブロックします。デフォルト値は 100 で、セキュリティ要件と環境に合わせて調整できます。

たとえば、max_connect_errors = 5000 の場合、ホスト X からの 5,000 回の接続要求後に中断されると、次のようなエラーが発生します。

Host X is blocked because of many connection errors ().

ホストのブロックを解除するには、次のコマンドを使用します。

mysql> flush hosts;
mysql> show global variables like 'max_connect_errors';

+| Variable_name      | Value |
+--------------------+-------+
| max_connect_errors | 5000|
+--------------------+-------+

1 row in set (0.00 sec)

結論

このブログ記事シリーズでは、RDS for MySQL で最も一般的にカスタマイズされたパラメータのベストプラクティスを紹介しました。RDS MySQL を使用する前に、潜在的な操作上の問題を回避するためにカスタムパラメータ値を確認することをお勧めします。


著者について

Saikat Banjeree は、アマゾン ウェブ サービスのクラウドサポートエンジニアです。