MySQL 8.0 リファレンスマニュアル


5.6.3.4 スレッドプールのチューニング

このセクションでは、秒あたりのトランザクション数などのメトリックを使用して測定された、最高のパフォーマンスを得るためのスレッドプールシステム変数の設定に関するガイドラインを提供します。

thread_pool_size はスレッドプールのパフォーマンスを制御するもっとも重要なパラメータです。 それはサーバーの起動時にのみ設定できます。 スレッドプールのテストにおける経験では、次のように示されます。

  • プライマリストレージエンジンが InnoDB である場合、最適な thread_pool_size 設定は、16 から 36 の間になる可能性があり、もっとも一般的な最適な値は 24 から 36 になる傾向があります。 36 を超える設定が最適であった状況はありませんでした。 16 未満の値が最適である特殊なケースがある場合もあります。

    DBT2 や Sysbench などのワークロードの場合、InnoDB の最適な値は通常 36 くらいであるようです。 著しく書き込みの多いワークロードでは、最適な設定はもっと少ない可能性があります。

  • プライマリストレージエンジンが MyISAM である場合、thread_pool_size 設定はかなり小さくするべきです。 最適なパフォーマンスは、多くの場合、4 から 8 の値で確認できます。 値を大きくすると、パフォーマンスにややマイナスでも劇的な影響を与える傾向はありません。

もう 1 つのシステム変数 thread_pool_stall_limit はブロックされたステートメントと長時間実行ステートメントの処理に重要です。 MySQL Server をブロックするすべての呼び出しがスレッドプールにレポートされる場合、実行スレッドがブロックされるといつでもわかります。 ただし、これは常には当てはまらないことがあります。 たとえば、ブロックはスレッドプールコールバックによってインストゥルメントされていないコードで発生する可能性があります。 そのような場合、スレッドプールはブロックされているように見えるスレッドを識別できる必要があります。 これは、thread_pool_stall_limit システム変数を使用してチューニングできるタイムアウトを使用して行われます。この値は 10ms 単位で測定されます。 このパラメータにより、サーバーは完全にブロックされることはありません。 thread_pool_stall_limit の値は、デッドロックされたサーバーのリスクを回避するため、6 秒の上限があります。

thread_pool_stall_limit により、スレッドプールは長時間実行ステートメントを処理することもできます。 長期間実行するステートメントがスレッドグループをブロックすることを許可された場合、グループに割り当てられるその他のすべての接続はブロックされ、長期間実行するステートメントが完了するまで実行を開始できません。 最悪の場合、これには数時間または数日かかることもあります。

thread_pool_stall_limit の値は、その値より長く実行するステートメントが停滞中とみなされるように選択するべきです。 停滞中のステートメントは、追加のコンテキストスイッチと場合によっては追加のスレッド作成が必要であるため、大量の追加のオーバーヘッドを生成します。 一方、thread_pool_stall_limit パラメータの設定が高すぎるということは、長時間実行されるステートメントが必要以上に長く実行されるステートメントをブロックすることを意味します。 待機の値が短いと、スレッドはよりすみやかに開始できます。 短い値はデッドロック状況を回避により適しています。 長い待機の値は、長時間実行するステートメントを含むワークロードで有用で、現在のステートメントの実行時に多数の新しいステートメントが開始しないようにします。

サーバーに負荷がかかっている場合でも、サーバーはステートメントの 99.9% が 100 ミリ秒以内に完了するワークロードを実行しており、残りのステートメントが 100 ミリ秒から 2 時間の間でまったく均等に分散してかかるものとします。 この場合、thread_pool_stall_limit を 10 (10× 10ms = 100ms) に設定すると意味があります。 デフォルト値の 6 (60ms) は、主に非常に単純なステートメントを実行するサーバーに適しています。

thread_pool_stall_limit パラメータは、サーバーのワークロードに対して適切なバランスをとることができるように、実行時に変更できます。 tp_thread_group_stats テーブルが有効になっていると仮定すると、次のクエリーを使用して、停止した実行済のステートメントの割合を判断できます:

SELECT SUM(STALLED_QUERIES_EXECUTED) / SUM(QUERIES_EXECUTED)
FROM performance_schema.tp_thread_group_stats;

この数値は可能なかぎり小さくするべきです。 ステートメントの停滞の可能性を削減するには、thread_pool_stall_limit の値を増やします。

ステートメントが到着したときに、それが実際に実行を開始するまで、遅延できる最大の時間はどれくらいですか。 次の条件が当てはまるとします。

  • 優先度が低いキューに 200 ステートメントが入れられています。

  • 優先度が高いキューに 10 ステートメントが入れられています。

  • thread_pool_prio_kickup_timer は 10000 (10 秒) に設定されています。

  • thread_pool_stall_limit は 100 (1 秒) に設定されています。

最悪の場合、10 個の優先度の高いステートメントは長時間実行し続ける 10 個のトランザクションを表します。 したがって、最悪の場合、ステートメントは常に実行を待機しているステートメントが含まれているため、優先度の高いキューに移動できません。 10 秒後、新しいステートメントは優先度の高いキューに移動される資格を得ます。 ただし、それが移動される前に、その前のすべてのステートメントも移動される必要があります。 優先度の高いキューに移動されるのは、1 秒あたり最大 100 ステートメントであるため、これはさらに 2 秒かかる可能性があります。 ステートメントが優先度の高いキューに到達したときに、多くの長時間実行ステートメントがその前にある可能性があります。 最悪の場合、これらのすべてが停止し、次のステートメントが優先度の高いキューから取得される前に各ステートメントに 1 秒が必要になります。 したがって、このシナリオでは、新しいステートメントの実行が開始されるまで 222 秒かかります。

この例では、アプリケーションの最悪のケースを示しています。 その処理方法はアプリケーションに依存します。 アプリケーションの応答時間に対する要件が高い場合、おそらくそれ自体で高いレベルでユーザーを制限するはずです。 そうでない場合は、スレッドプール構成パラメータを使用して、何らかの最大待機時間を設定できます。


関連キーワード:  ステートメント, サーバー, 実行, 変数, thread, pool, 設定, プール, limit, インストール