スマートスタイル TECH BLOG

データベース&クラウド技術情報

MTS(マルチスレッドスレーブ)を使う場合の注意点

MySQL5.6で実装されたMulti Threads Slave(以下、MTS)は、MySQLレプリケーションを利用するユーザ共通の悩みである「スレーブ遅延」に対するソリューションの一つです。
スレーブ遅延の主因の一つは、スレーブのSQLスレッドが「1つ」しかないことでした。しかし、MySQL5.6からMTSを用いることで異なるデータベース間で複数スレッドによる並列処理が可能となり、MySQL5.7からは同一データベースでも並列処理が可能となりました。この結果、スレーブの遅延はかなり軽減されています。

しかし、以前MTSの検証をしていて気になる挙動を見つけたので、記載したいと思います。

事象の内容

きっかけは大きなバッチ処理を実行した時、マスタの実行時間よりも大幅に長くスレーブでの処理に時間がかかってしまう、という事象でした。

調査を進めるうちにエラーログに以下のようなメッセージが大量に出力されているのが分かりました。

上記のメッセージは、マスタから送られたレプリケーションイベントのサイズが、スレーブのworkerスレッドの使用メモリ量を超えてしまった場合に、処理が待ち状態になっていることを示しています。「workerスレッドの使用メモリ量」は、slave_pending_jobs_size_max変数で決められます。

再現手順

AWSの「c5.xlarge」インスタンスを3台作成し、MySQL5.7の最新版をyumインストールします(この時点ではMySQL5.7.21)。
その後、「マスタ1台:スレーブ2台」のGTIDレプリケーション環境を構築し、MTSを設定します。なお、パラメータは以下の通り変更します。

master : max_allowed_packet=32MB
slave1 : max_allowed_packet=32MB / slave_pending_jobs_size_max=16MB
slave2 : max_allowed_packet=32MB / slave_pending_jobs_size_max=128MB

※ slave_parallel_workers変数は “4” で統一しています

この環境で、マスタでランダムデータのINSERT文を実行しています。

するとトランザクションのサイズが一定を超えた段階で、以下のようなメッセージがslave1のエラーログに出力されます。この時、スレーブで大幅な遅延が起きている可能性があります。

※ 別コンソールで tail -f /var/log/mysqld.log を実行しておくと分かりやすいです

一方で、slave_pending_jobs_size_max変数を大きく設定しているslave2では同様のメッセージは発生していません。

対策

上記の問題を回避するためには、slave_pending_jobs_size_max 変数をあらかじめ大きくすることが推奨されます。特にマスタで巨大なトランザクションが実行されるケースが想定されるなら、ある程度大きい数値を設定すると良いでしょう。
また、max_allowed_packet > slave_pending_jobs_size_max という設定をしてしまうと、ペンディングが頻発する可能性があります。slave_pending_jobs_size_max のデフォルト値は「16MB」と少し小さめなので、注意しましょう。

参考URL

Multi-Threaded Slave Statistics
17.1.4.3 レプリケーションスレーブのオプションと変数


MySQL

 

Return Top