問題
ApsaraDB RDS for MySQL/MariaDB インスタンスの CPU 使用率が高く、場合によっては 100% に達します。
原因
本トピックでは、CPU 使用率が 100% になる 2 つの一般的な原因、つまり高いアプリケーション負荷 (高い QPS) と遅い SQL クエリによる高いクエリコスト、およびそれぞれの解決策について説明します。アプリケーションがクエリまたはデータ変更操作を送信すると、システムは多数の論理読み取り操作を実行します。論理 I/O とは、クエリを実行するためにテーブル内でアクセスする必要があるデータ行の数を指します。その結果、システムはストレージからメモリに読み込まれたデータの整合性を維持するために、大量の CPU リソースを消費します。MySQL では、高い CPU 使用率は、多くの場合、多数のテーブル行にアクセスするコストの高い遅い SQL クエリが原因です。
本トピックでは、多数の行ロックの競合、ロック待機、またはバックグラウンドタスクに起因する CPU 使用率の上昇は、まれなケースであるため扱いません。
-
高いアプリケーション負荷 (高い QPS):
-
特徴:インスタンスでは、最適化の余地がほとんどない、シンプルで効率的なクエリで高い QPS が発生します。
-
症状:遅い SQL クエリは観測されないか、あってもそれが主要な原因ではありません。QPS と CPU 使用率の傾向は一致しています。
-
一般的なシナリオ:この問題は、注文システム、読み取り率の高い人気の Web アプリケーション、Sysbench などを使用したサードパーティのストレステストなど、最適化されたオンライン トランザクション処理 (OLTP) システムでよく見られます。
-
-
遅い SQL クエリによる高いクエリコスト (多数の行へのアクセス):
-
特徴:インスタンスの QPS は高くないものの、クエリの実行が非効率で、大量のテーブルデータのスキャンが必要です。最適化の余地が大きいです。
-
症状:遅い SQL クエリが見られます。QPS と CPU 使用率の傾向が一致しません。
-
原因分析:クエリの効率が低いため、システムは結果を返すために大量のデータにアクセスする必要があり、平均論理 I/O が高くなります。したがって、(たとえば、トラフィックの少ない Web サイトのように) QPS が高くない場合でも、インスタンスの CPU 使用率は高くなる可能性があります。
-
解決策
ご自身の状況に合わせて解決策を選択してください。
高いアプリケーション負荷 (高い QPS)
高い CPU 使用率が高いアプリケーション負荷によって引き起こされる場合、SQL の最適化の余地はほとんどありません。この問題は、アプリケーションアーキテクチャまたはインスタンス設定を調整して対処します。
-
インスタンスタイプをアップグレードして CPU リソースを増やします。詳細については、「設定変更」をご参照ください。
-
読み取り専用インスタンスを追加し、製品カテゴリや列車の時刻表の検索など、データの一貫性要件が厳しくないクエリを読み取り専用インスタンスにルーティングします。これにより、プライマリインスタンスの負荷が軽減されます。詳細については、「MySQL 読み取り専用インスタンスの作成」をご参照ください。
-
クラウドネイティブ分散データベースである PolarDB-X を使用して、データを自動的にシャーディングし、クエリ負荷を複数の RDS インスタンスに分散します。
-
ApsaraDB for Memcache または Tair を使用して、頻繁にアクセスされるクエリ結果をキャッシュから提供し、RDS インスタンスの負荷を軽減します。
-
データが比較的静的で、クエリの繰り返しが多く、結果セットが 1 MB 未満のアプリケーションの場合は、クエリキャッシュを有効にすることを検討してください。
説明クエリキャッシュの有効化がアプリケーションに有益かどうかをテストしてください。設定の詳細については、「ApsaraDB RDS for MySQL のクエリキャッシュの設定と使用」をご参照ください。
-
履歴データを定期的にアーカイブします。シャーディングまたはパーティショニングを使用して、クエリによってアクセスされるデータ量を削減します。クエリを最適化して実行コストを削減し、アプリケーションのスケーラビリティを向上させます。
遅い SQL クエリによる高いクエリコスト
この問題を解決するには、非効率なクエリを特定し、その実行効率を向上させ、実行コストを削減します。
-
次のいずれかの方法を使用して、非効率なクエリを特定します。
-
次の SQL ステートメントを実行して、現在実行中のクエリを表示します。
show processlist; show full processlist;システムは次のような出力を返します。
mysql> show processlist; +----------+-------+-------------------+---------+---------+-------+--------------+----------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----------+-------+-------------------+---------+---------+-------+--------------+----------------------------------------------+ |101031643 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |117731567 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |134298793 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |134384670 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 0 | Init | show processlist | |234891284 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |235125098 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |235200576 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |235633985 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |235887773 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |251990394 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | |252662718 | jacky | xxx.xxx.xxx.xx:xx | my_test | Query | 10760 | Sending data | select b.* from perf_test_no_idx_01 a, ... | +----------+-------+-------------------+---------+---------+-------+--------------+----------------------------------------------+ 11 rows in set (0.00 sec)長時間実行されており、[Sending data]、[Copying to tmp table]、[Copying to tmp table on disk]、[Sorting result]、[Using filesort] などの状態にあるクエリセッションは、パフォーマンスに問題がある可能性があります。
-
高い QPS が高い CPU 使用率を引き起こすシナリオでは、クエリは通常、迅速に実行されます。
show processlist;コマンドを使用したり、インスタンスセッションを表示したりして、現在実行中のクエリをキャプチャするのが難しい場合があります。ただし、次の SQL ステートメントを実行してクエリを分析することはできます。explain [$SQL]説明[$SQL] は、パフォーマンスに問題のある SQL クエリを表します。
-
kill [$ID];のようなコマンドを実行して、長時間実行されているセッションを終了できます。詳細については、「ApsaraDB RDS for MySQL インスタンス上のセッションの終了」をご参照ください。説明[$ID] は、クエリに対応するセッション ID を表します。
-
-
データベース自律サービス (DAS) を使用して、現在実行中のクエリを表示します。
にログインします。DASコンソール.
左側のナビゲーションウィンドウで、インスタンスモニター.
表示されるページで、管理するデータベースインスタンスを見つけ、インスタンスIDをクリックします。 インスタンス詳細ページが表示されます。
左側のペインで、インスタンスセッション をクリックします。
-
[SQL] 列のクエリテキストをクリックして、完全なクエリとその実行計画を表示します。
-
[SQL インサイトと監査]を使用して、SQL の実行パフォーマンスを継続的に監視します。インスタンス詳細ページの左側メニューで、[自律サービス] > [SQL インサイトと監査] を選択します。SQL 実行時間やスキャンされた行数などの詳細情報を表示して、CPU を集中的に使用する SQL ステートメントを特定できます。
-
-
最適化が必要なクエリを特定した後、Data Management Service (DMS) コンソールの SQL 診断を使用して、最適化の提案を取得します。また、過去の問題のトラブルシューティングには、診断レポートも非常に役立ちます。
-
DMS コンソールを使用してデータベースにログインします。
-
ページの上部にある [SQL ウィンドウ] をクリックし、目的のデータベースを選択します。
-
クエリステートメントを SQL ウィンドウに貼り付け、[SQL 診断] をクリックして最適化の提案を取得します。診断結果には、SQL ステートメント、実行計画 (クエリタイプ、関連テーブル、スキャン行数を表示)、および直接実行可能な DDL ステートメントを含むインデックスに関する提案が含まれます。
-
-
推奨される最適化を適用します。たとえば、提案されたインデックスを追加した後、クエリの実行コストが大幅に低下することを確認します。
短期的な緩和策
CPU 使用率が高いままで、遅い SQL クエリを迅速に最適化できない場合は、次の対策を使用して CPU 負荷を緩和します。
SQL スロットリングを使用すると、遅い SQL クエリの同時実行数を制御できます。
-
ApsaraDB RDS コンソールにログインします。 [インスタンス] リストで、対象のインスタンスをクリックします。
-
左側メニューで、[自律サービス] > [ワンクリック診断] を選択します。
-
[セッション管理] タブをクリックします。
-
[SQL スロットリング] ボタンをクリックします。
-
[スロットリングルールの作成] をクリックし、スロットリングモード、ルール、データベース、最大同時実行数、およびスロットリング期間を設定します。
インスタンスタイプを一時的にアップグレードします。
セッションの強制終了と SQL スロットリングで CPU 負荷を緩和できない場合は、インスタンスタイプを一時的にアップグレードして CPU リソースを増やすことができます。インスタンスの基本情報ページで、設定情報セクションの [設定変更] をクリックしてインスタンスをアップグレードします。詳細については、「設定変更」をご参照ください。
詳細情報
パフォーマンス問題のトラブルシューティング機能
Data Management Service (DMS) は、インスタンスのパフォーマンス問題のトラブルシューティングと解決に役立ついくつかの機能を提供します。診断レポートは、ApsaraDB RDS for MySQL および ApsaraDB RDS for MariaDB インスタンスのパフォーマンス問題をトラブルシューティングするための最も効果的なツールです。パフォーマンス問題の原因が何であれ、常に診断レポート、特に SQL 最適化、セッションリスト、および遅い SQL クエリの概要セクションを確認することから始めてください。
CPU 使用率 100% の防止
CPU 使用率が 100% に達するのを防ぐには、以下のガイドラインに従ってください。
-
CPU 使用率のアラームを設定し、インスタンスの CPU リソースに十分な余力があることを確認します。
-
アプリケーションの設計および開発段階で、クエリの最適化を考慮してください。一般的な MySQL の最適化原則に従い、クエリの論理 I/O を削減して、アプリケーションのスケーラビリティを向上させます。
-
新しい機能やモジュールをリリースする前に、本番データでストレステストを実行してください。
-
新しい機能やモジュールをリリースする前に、本番データで回帰テストを実行してください。
システムリソースアルゴリズム
次の簡略化されたモデルは、システムリソース、SQL ステートメントの実行コスト、および秒間クエリ数 (QPS) の関係を示しています。
-
条件:アプリケーションモデルは一定であり、つまりアプリケーションコードは変更されません。
-
avg_lgc_io:各クエリの実行に必要な平均論理 I/O。 -
total_lgc_io:インスタンスの CPU リソースが単位時間あたりに処理できる論理 I/O の総量。 -
式:
total_lgc_io = avg_lgc_io × QPS、つまり単位時間あたりの総 CPU リソース = クエリあたりの平均論理 I/O × 秒間クエリ数。
関連ドキュメント
データベース自律サービスを使用して ApsaraDB RDS for MySQL インスタンスの高い CPU 使用率を解決する
対象バージョン
-
ApsaraDB RDS for MySQL
-
ApsaraDB RDS for MariaDB