...

MariaDBのスレッドキャッシュを効率的に設定する:オーバーヘッドを抑えつつパフォーマンスを向上させる

接続の確立やスレッドの作成にかかる負荷を軽減するために、MariaDBのスレッドキャッシュを意図的に調整しています。これにより、 レイテンシー そして節約 CPU‑オーバーヘッド。特に、短いセッションが多く、接続頻度が高い場合に顕著である。.

中心点

以下の点は、キャッシュの効果的な設定と測定のための指針となります。ここでは、明確な 価値観 かつ実践可能な ステップ.

  • 作用原理: 高コストな新規生成の代わりに、終了したスレッドを再利用すること
  • 関連性: 1秒間に多数の短い接続がある場合に役立つ
  • 測定: Threads_created、Connections、Threads_cached
  • バウンダリー: スレッドプールが有効な場合は無視される
  • 手続き: 少額から始め、状況を見極め、慎重に増やしていく

MariaDBのスレッドキャッシュの仕組み

接続が切断された後、MariaDB は制限に達するまでそのスレッドをキャッシュに保存します。新しい接続はこのスレッドを再利用できるため、コストのかかるスレッドの生成を省略でき、 応答時間 を低減します。これは、1秒あたりのログイン数が多く、セッションが短いワークロードにおいて特に効果を発揮し、スレッドの作成と破棄が顕著な コスト要因 となります。キャッシュは約5分間操作がないとクリアされるため、サーバーに不要な負荷がかかることはありません。スレッドプールがない場合、デフォルト値は多くの場合256に設定されており、これは一般的なアクセス集中時に備えてわずかなバッファを確保するものです。 なお、再利用によってすべての問題が解決されるわけではない点にも留意してください。接続状態の悪化やクライアント側の不適切な処理は依然として顕在化し、別途修正が必要となります。.

チューニングが割に合うのはいつなのか

アプリケーションが多数の短時間の接続を生成し、カウンターが スレッド作成 急速に増加している。その明確な兆候として、Threads_created を Connections で割った値が高いことが挙げられる。これは、再利用が目的を果たせていないケースが多すぎることを示している。この場合、新しいスレッドが CPU これらは応答時間を悪化させますが、Reuseはパスを短縮します。ただし、私は常に、不要な再接続など、原因がクライアント側にあるのではないかと確認するようにしています。適切な接続処理によって負荷が安定すれば、キャッシュの設定は多くの場合、わずかな調整で済むものです。 やみくもに最大化を図ると、すぐにメモリ消費の代償を払うことになり、アプリケーションロジックにおける真の調整ポイントを見落としてしまうことになります。.

事前に確認する測定値

正確な診断を行うために、私は数は少ないが示唆に富む指標と、明確な計算式を用いています。まず最初に、私は スレッド作成, コネクション, スレッド_キャッシュ済み そして スレッド接続 を確認し、傾向を分析する。Threads_created/Connections という単純な比率を見れば、データベースが再利用せずに再構築される頻度を把握できる。また、Threads_cached が通常の同時接続数のピーク値にどれだけ近いかという点も非常に参考になる。キャッシュとピーク値との差が大きいままの場合は、私は リソース あるいは、その 負荷 いいえ。以下の表には、重要な指標とその直接的な意味がまとめられています:

キーパーソン 意味 解釈 アクション
スレッド作成 起動以降の新規スレッド 急速な成長は、頻繁な再生を示唆している キャッシュを確認し、クライアントの再接続を減らす
コネクション 接続総数 クォータおよびトレンド評価の基礎 ピーク負荷の推移を監視する
スレッド_キャッシュ済み キャッシュ内のスレッド 周波数が高いにもかかわらず低値である場合は、値が小さすぎる可能性がある キャッシュを少しずつ増やしていく
スレッド接続 現在アクティブな接続 適切なキャッシュサイズの目安 典型的なピーク付近のキャッシュを適切に設計する

実務における段階的な調整

まず、現実的な負荷条件下での測定から始め、変更を行うたびに主要指標を記録します。その後、現在の値を SHOW VARIABLES LIKE 'thread_cache_size' そして、その ベース 後で 比較. その後、少しずつ値を増やしていき、「Threads_created」の増加ペースが緩やかになり、接続時間が安定するかどうかを確認します。一度に大きな変更を加えると原因が判別しにくくなるため、意図的に小さく、検証可能なステップを踏みながら進めています。 各調整の後、その効果が信頼できるものとなるよう、十分な負荷がかかるフェーズを待ちます。複数の負荷ウィンドウで結果が裏付けられて初めて、次のステップを検討します。.

推奨される設定ロジックと初期値

普遍的な理想値というものは存在しないため、私は典型的なピーク値や過去のデータに基づいて判断しています。低速または中程度の通信速度の場合、特に以下の標準値に近い場合は、小~中規模のキャッシュで十分なことがよくあります。 256. 負荷の変動が激しく、1秒あたりの接続数が多いため、再利用率が実際に高まる限り、キャッシュの範囲を広く設定すると効果的です。私は、不要な リソース バインドします。キャッシュを巨大にすると、メリットも得られないままメモリを無駄にすることになります。さらに、次のような付随するバックグラウンドスレッドも確認しています。 Page Cleanerのスレッド, 、というのも、I/O アクティビティが高い場合、これらも全体的な動作に影響を与えるからです。.

スレッドごとのメモリ要件とキャッシュサイズの影響

私はキャッシュの保存効果を意図的に計算に組み込んでいます。キャッシュされたスレッドは、主にその thread_stack および少量のスレッドメタデータが存在します。接続ごとのバッファとして、例えば ソート・バッファ・サイズ, 結合バッファサイズ あるいは、ネットワークバッファは切断時に解放されるため、キャッシュに永続的な負荷をかけることはありません。一方、スタックはスレッドに紐づいたままとなります。経験則として、私は次のように設定しています: キャッシュメモリ ≈ thread_cache_size × thread_stack (若干のオーバーヘッドを加えたもの)。ある thread_stack 256~320 KBに加え、512のキャッシュがあると、すでに130~170 MB規模のメモリが占有されることになります。 スタックを増やしたり、非常に大きなキャッシュを使用したりする場合は、この影響に留意し、より重要なバッファ(InnoDBバッファなど)とのバランスを考慮する必要があります。.

そのため、私は常に次の点を確認しています:

  • SHOW VARIABLES LIKE 'thread_stack'; スレッドごとに割り当てられたメモリ量を把握するために
  • ~の近く スレッド_キャッシュ済み の95パーセンタイルのピーク値について スレッド接続
  • キャッシュの拡大が視聴率に 作成されたスレッド数 / 接続数 実際に改善された

効果が得られない場合は、再びキャッシュを縮小します。キャッシュが大きすぎるかどうかは、以下の点から判断できます。 スレッド_キャッシュ済み 遅延がさらに低下することなく、通常の接続ピーク値を恒常的に上回っている。.

Linuxおよびコンテナ環境での運用:制限事項と課題

キャッシュの制限値を引き上げる前に、システム全体の制限を確認します。データベース自体が最大接続数に達するずっと前に、OSの制限によってスレッドの作成が失敗する可能性があります。その際、以下の点を確認します:

  • プロセス/スレッドの境界: ulimit -u (最大プロセス数/スレッド数)、, /proc/sys/kernel/threads-max そして /proc/sys/kernel/pid_max
  • スタック上限: ulimit -s スレッドごとに確保されるスタックに影響を与える――結果として、大規模なキャッシュにおいて重要となる
  • コンテナ内のcgroups: pids.max およびメモリ制限。PIDの制限が厳しすぎると、バースト処理が妨げられる
  • スケジューラー印刷: プールを使用しないスレッドが非常に多い場合、コンテキスト切り替えのオーバーヘッドが増加する可能性があります。このような場合、スレッドプールやアプリケーションプーリングの方が適している場合があります

マルチソケットまたはNUMAホストでは、スレッドがノード間を移動し、それによって遠隔メモリアクセスが発生していないかについても確認しています。このような環境では、スケジューラによって広範囲に分散される新しいスレッドを絶えず生成するよりも、安定したプールの方が効率的であることが多いのです。.

スレッドキャッシュに関するよくある誤解

一般的な誤解を払拭し、的を絞って最適化を図ります:

  • „「キャッシュが増えれば増えるほど、どんどん速くなる。」“ 実際に多くの新しいスレッドが生成される場合のみ、キャッシュが有利になります。そうでなければ、無駄にメモリを消費することになります。.
  • „「キャッシュにより、認証処理が高速化されます。」“ キャッシュは主にOSスレッドの作成を省く役割を果たします。認証、TLSハンドシェイク、および必要に応じて行われるDNSルックアップは、接続ごとに実行されるため、これらについては依然として個別に最適化が必要です。.
  • „「スレッドごとのバッファは使用されたままになる。」“ 切断後、これらのバッファは解放されます。キャッシュには主にスレッドのスタックが残ります。.
  • „「キャッシュを十分に確保すれば、アプリ・プーリングの代わりになる。」“ サーバー側のキャッシュはコストを軽減しますが、アプリケーション側のプール化はコストそのものを回避します。私は常に、アプリケーションのプール化を最初の対策として検討しています。.

TLS、DNS、および認証の影響

キャッシュがすべての部分をカバーしているわけではないため、接続時間を多角的に評価しています。高い 握手時間 私はこれを、多くの場合、TLSに関する問題(証明書の検証、再開の失敗)やDNSの逆引き解決の問題だと解釈しています。 skip_name_resolve=ON 高コストなリバースルックアップを避け、IPベースのグラントを利用しています。また、認証プラグインの選択や設定もログインパスに影響を与えます。一方、スレッドキャッシュは主に以下のコストを削減します。 スレッドの作成と破棄. キャッシュ容量が十分にあるにもかかわらず、Connectのレイテンシが依然として高い場合は、TLSパラメータ、DNS、およびクライアントの接続管理に焦点を当てます。.

判断基準:キャッシュ、スレッドプール、それともアプリケーションプール?

私は、単純な道筋に沿って決断を下す:

  • アプリプーリングは利用可能ですか? その場合は、正確に寸法を決定してください。沈下します スレッド作成 明らかに、バッファとしては小~中規模のキャッシュで十分です。.
  • スレッドプールは有効ですか? そこで、 スレッドキャッシュサイズ いいえ。他の調整を行う前に、まずプールをチューニングし、待ち時間を測定します。.
  • プールを設定せずに短い接続を多数行う? キャッシュを適度に増やす。目標:割合が明らかに低下すること 作成されたスレッド数 / 接続数 そして、接続時間が比較的少ない時間帯。.
  • 並列処理の度合いが非常に高く、スケジューラへの負荷も大きい? ワークスティーリングやより厳格なワーカー割当を実現できるスレッドプールへの切り替えを検討しています。.

重要なのは「元に戻す」という対応策です。あるアプローチが測定可能なほど効果的でない場合は、前回の変更を元に戻します。そうすることで、データに密着した状態を保ち、見返りのない複雑さを回避できるのです。.

測定手法とクエリ例

進捗状況を確認するために、再現可能なクエリを使用しています。現状を把握するために:

  • SHOW GLOBAL STATUS LIKE 'Threads\_%'; 用品 スレッド作成, スレッド_キャッシュ済み, スレッド接続
  • SHOW GLOBAL STATUS LIKE 'Connections'; 割当の算定基準として
  • SHOW VARIABLES LIKE 'thread\_%'; に於いて スレッドキャッシュサイズ そして thread_stack 検討する

この割合は、例えば次のように計算します:

SELECT 
  ROUND(tc.variable_value+0 / NULLIF(c.variable_value+0,0), 4) AS threads_created_per_connection
FROM information_schema.GLOBAL_STATUS tc
JOIN information_schema.GLOBAL_STATUS c
  ON tc.variable_name='Threads_created' AND c.variable_name='Connections';

負荷テストでは、時間枠を採用しています。2つのスナップショット(5~10分間のインターバルの開始時と終了時)を取得し、その差分を算出します。必要に応じて、隔離されたテスト環境では フラッシュステータス, 、カウンタをリセットするため――本番環境では、他の分析結果に影響を与えないよう、この操作は避けています。 クォートに加えて、クライアントモニタリングから取得した接続時間の95パーセンタイルと99パーセンタイルも保存しています。なぜなら、まさにそこがレイテンシのピークに与える影響が顕著に現れる箇所だからです。.

確認:キャッシュ容量が不足しています

キャッシュ容量が小さすぎることは、負荷が一定であるにもかかわらず「Threads_created」が急激に増加することから、よくわかります。同時に、システムが多くの接続を処理しているにもかかわらず「Threads_cached」は低いままとなり、利用率が低下します。その結果、変動が生じます。 遅延時間 そして不必要な CPU- 頻繁なスレッド作成による負荷。キャッシュが適度に増加し、指標が安定すれば、その診断が正しいことが裏付けられます。処理時間が落ち着き、パフォーマンスが明らかに向上すれば、正しい方向に進んでいることになります。効果が現れない場合は、クライアント側の原因、ネットワークの問題、またはストレージのボトルネックを重点的に調査します。.

検知:キャッシュが大きすぎる

キャッシュが大きすぎると気づかれにくいですが、他のバッファ対象が利用できないメモリを占有してしまう可能性があります。その場合、すでに良好な比率を示していますが、キャッシュを増やしても状況はほとんど変わらず、かえって リソース. Threads_cached が通常のピーク値を恒久的に大幅に上回っている場合、そのメリットは失われてしまいます。 私は段階的に値を下げながら、指標や応答時間に変化がないかを確認しています。すべてが安定していれば、より小さく効率的な設定を採用します。そうすることで、インスタンスをスリムに保ち、InnoDBバッファやクエリキャッシュの代替構造といった、より重要なメモリ領域のための余裕を確保しています。.

特徴:スレッドプールが有効

スレッドプールが稼働し始めると、MariaDB は変数 `thread_cache_size` を完全に無視します。このモードでは、1 つのプールが少数のワーカーを制御し、それらが多数の接続を処理することで、新しいスレッドの待機時間を防ぎます。私は負荷プロファイルに基づいて、プール化を行うかどうかを判断します。 アプローチは、あるいはキャッシュがさらに 柔軟性 を提供します。高度に並列化されたワークロードは、多くの場合このプールの恩恵を受けますが、従来のログインピーク時はキャッシュの再利用によってうまく機能します。このプールを利用する場合は、そのパラメータに焦点を当て、thread_cache_size は考慮しないようにします。良い出発点として、以下の資料を読むことをお勧めします。 MariaDB スレッドプール, 、さらなるチューニングの手順を計画する前に。.

アプリケーションのコネクションプーリングとの連携

私はアプリ側のプール方式を好みます。これは、接続を維持しつつ、データベースサーバーの負荷を軽減できるからです。高負荷下でも Threads_created の値が低いままなら、それはプーリングが効果的に機能しており、追加のキャッシュの必要性が低いことを示しています。この構成では、時折発生する負荷のピークを緩和するだけで、 リソース 無駄になります。一方、頻繁な再接続が見られる場合は、まず適切なアプリ・プーリングを調整し、その後にデータベース設定の規模拡大を検討します。アイドル時間とプールサイズを確認することで、負荷を均一化する最適なバランスを見つけることができます。 役立つ入門情報は、以下の実践ガイドにまとめられています。 コネクション・プーリング, 、これはキャッシュの最適化と並行して活用しているものです。.

例:設定と制御

まず、以下のコマンドで現在の設定を確認します。 SHOW VARIABLES LIKE 'thread_cache_size' そして、負荷を記録します。その後、試しに次のような適度な値を設定します。 SET GLOBAL thread_cache_size = 256; 或いは 512, 、設定に応じて。重要なのは、設定ファイル(例えば my.cnf に於いて [mysqld], 、再起動後も設定が維持されるようにするためです。以下の負荷ウィンドウでは、次のような現象を確認しています スレッド作成 および関連する 引用, 、明確な傾向が見えるまで。新規生成数が著しく減少すれば、キャッシュは目的を果たしていることになる。数値に変化がない場合は、値をさらに上げる前に、接続管理に原因がないか調べる。.

実践ガイド:ガイドラインに基づくサイジング

私は、やみくもに最大化を図るのではなく、信頼性の高い目安に基づいて作業を行っています:

  • スタート: 現在の最高値は スレッド接続 (いくつかの典型的な負荷ウィンドウにわたって)観察する。.
  • 初期の寸法決定: キャッシュ ≈ 通常のピーク時の70~90 %, 、さらに次のような上限によって制限されており、 max_connections / 2 安全限界として。.
  • ステップ幅: 64~128の範囲で少しずつ増やし、比率を 作成されたスレッド数 / 接続数 チェックする。
  • 目標範囲: 接続時間の割合が大幅に低下し、95パーセンタイルの値も落ち着いている。この効果が現れない場合は、キャッシュを解除する。.
  • 永続性: MariaDB の以下のバージョン以降では SET PERSIST テスト済みの値をサーバー側で直接保存します。そうでない場合は、 my.cnf.
  • ロールバック: 変更を行う前には、万が一のときにすぐに元に戻せるよう、その前の値を必ず記録しておく。.

昼夜の負荷パターンが大きく異なる環境では、夜間に不必要に多くのストレージを占有することなく、ピーク負荷を平滑化するような保守的な設計を推奨します。特殊な負荷(デプロイやCronジョブの集中処理など)に対しては、意図的にバッファを確保するようにしています。.

トラブルシューティング・チェックリスト

まず、スレッドプールがアクティブであり、それによってキャッシュが無効化されているかどうかを確認します。その後、単なるスナップショットを撮るのではなく、複数の時間枠にわたって Threads_created / Connections の比率を測定します。 その後、Threads_cached を Threads_connected のピーク値と比較し、リソースの過不足を特定します。パフォーマンスが依然として低い場合は、アプリケーションの再接続、ネットワーク遅延、および I/O 待機時間の増加といったストレージ関連の兆候を調査します。 最後に、スレッドに影響を与える競合する設定を確認し、再現性のあるテストシナリオを提示します。そうして初めて、明確な結論を導き出し、確固たるデータに基づかない安易な対応を回避できるのです。.

お急ぎの方のためのショートバージョン

スレッドキャッシュを使用してスレッドを再利用し、生成コストを削減しています。これは接続頻度が高い場合に効果を発揮しますが、アクティブなスレッドプールではこの変数は無視されます。その効果は、以下の比率の低下によって測定できます。 スレッド作成 にとって コネクション そして、接続時間が安定します。私は小規模から始め、一貫して測定を行い、数値やプロファイルがそれを正当化する場合にのみスケールアップします。クライアント側のプーリングは多くの場合、より大きな効果をもたらすため、まずそちらを確認します。そうすることで、オーバーヘッドを抑えつつパフォーマンスを向上させ、設定をスリムに保つことができます。.

現在の記事