現象記述
TDSQL-C for MySQLで応答遅延、接続不能、タイムアウトなどの現象が発生します。TDSQL-C for MySQLのCPU使用率が80%を超える場合、ビジネス応答遅延、タイムアウト、データベース接続不能などの現象が発生する可能性があります。
障害リスク
TDSQL-C for MySQLのCPU使用率が長時間にわたり過度に高い状態が続くと、データベースの全体のパフォーマンスに深刻な影響を及ぼします。極端な場合、インスタンスがHANG状態になる可能性があります。
HAがインスタンスのHANGを検知した場合、ユーザーの業務高可用性を確保するため、プライマリ/スタンバイ切り替えがトリガーされます。切り替え過程中、業務は一時的に利用不可となり、通常は60秒を超えません。業務ピーク時に切り替えが発生した場合、業務の安定性と継続性に深刻な影響を与える可能性があります。
CPUリソース不足による業務への影響を避けるため、CPU使用率が過度に高いインスタンスについては、事前に業務最適化を実施するかCPUリソースのアップグレードを行うことをお勧めします。インスタンスでプライマリ/スタンバイ切り替えが発生すると秒単位の瞬断が生じるため、長い接続を維持するアプリケーションには再接続メカニズムの実装が必要です。
考えられる原因
TDSQL-C for MySQLでは、主にシステムスレッドとユーザースレッドの2種類のスレッドがCPUを占有します。したがって、TDSQL-C for MySQL専用のCVM上では、これらの2種類のスレッドの状況に注目するだけで、ほとんどの障害シナリオを解決できます。
ユーザスレッド
ユーザースレッドのビジー状態は、ほとんどのケースで「スロークエリ」によって引き起こされます。「スロークエリ」要因以外に、「計算量の多さ」および「高QPS」要因があります。
スロークエリ
長時間の計算を実行する場合、例えば:order by、group by、一時テーブル、join など。この種の問題はクエリ効率が低く、単一のSQL文が長時間CPU時間を占有する結果となります。
計算量が多い
単純にデータ量が多いため、計算量が多くなります。
高QPS(Queries Per Second)
単純にQPS負荷が高いため、CPU時間が完全に消費されます。例:4コアのサーバーで20kから30kのポイントクエリを処理する場合、各SQLが占めるCPU時間は多くありませんが、全体のQPSが非常に高いため、CPU時間が占有されます。
システムスレッド
実際の環境では、システムスレッドに問題が発生するケースは比較的少なく、一般的に複数のシステムスレッドが同時にフル稼働状態になることは稀です。CVMの利用可能なコア数が4以上であれば、通常はCPU使用率が過度に高くなることはありません。ただし、一部のバグが影響を及ぼす可能性があります。詳細は下図をご参照ください:
解決の考え方
ほとんどの障害シナリオは、基本的にユーザースレッドのビジー状態が原因です。したがって、本稿ではユーザースレッドによるCPU使用率の過度な上昇問題に焦点を当て、対応するソリューションを提供します。
スロークエリ:DBbrainを使用した調査と最適化をお勧めします。詳細についてはスロークエリを参照してください。 計算量が多い:処理するデータ量が多いため、CPU使用率が過度に高くなります。対応策の詳細については計算量が多いを参照してください。 高QPS:アクセス量が過大なため、CPU使用率が過度に高くなります。対応策の詳細については高QPSを参照してください。 処理手順
CPU使用率の過度な上昇を引き起こす異常なSQL文は、DBbrainを用いて診断と最適化が可能です。
TDSQL-C for MySQLのスロークエリ時間(long_query_time)のデフォルト値は1秒です。性能問題が発生した場合、スロークエリが存在しないと判明したら、パラメータ値を引き下げ、業務サイクル内のスロークエリを観察した上で最適化することを推奨します。パラメータ調整後も業務サイクル内でスロークエリが確認できず、CPU使用率が依然として高い場合、CPU構成のアップグレードによりデータベース全体の性能向上を図ることをお勧めします。
データ量が比較的多い場合、インデックスや実行計画に問題がなくてもCPU使用率が過度に高くなることがあります。さらに、MySQLのワンスレッド・パー・コネクション(one-thread-per-connection)という特性と組み合わせると、それほど多くの並行処理がなくてもCPUリソースを使い切ってしまう可能性があります。
一般的に言って、この種の問題には以下の二つの比較的標準的な解決策があります:
読み書き分離:この種のクエリを普段の業務でほとんど使用されない読み取り専用スレーブDBにリダイレクトします。
プログラムセグメント内でSQLを分割し、単一の大規模クエリを複数の小規模クエリに分解します。
CPU構成のアップグレードにより、データベース全体の性能を向上させます。
読み取り専用インスタンスをマウントすることで、読み書きインスタンスの負荷を分散します。
クエリ文を最適化することで実行効率を向上させます。