「高可用性」の章で説明したように、OceanBaseデータベースのデータリンクはAPPServer <-> OBProxy <-> OBServerです。APPServerはデータベースドライバを介してODPに接続し、リクエストを送信します。OceanBaseデータベースの分散アーキテクチャにより、ユーザーデータは複数のパーティションとレプリカに分かれて複数のOBServerに分散されています。ODPはユーザーリクエストを最適なOBServerに転送して実行し、その結果をユーザーに返します。各OBServerにもルーティング転送機能があり、リクエストが現在のノードで実行できない場合は、正しいOBServerに転送します。
エンドツーエンドのパフォーマンス問題が発生した場合(データベースシナリオでは、エンドツーエンドとはアプリケーションサーバー上でSQLリクエストのRTが非常に高いことを指します)、まずはデータベースアクセスリンク上のどのコンポーネントに問題があるかを特定し、次にコンポーネント内の具体的な問題を調査する必要があります。
一般的に、2つの調査手法があります:
ドリルダウン調査法
データアクセスの順序に従ってリンク上の各コンポーネントを順次調査し、そのコンポーネントが下流コンポーネントを呼び出す時間を観測し、時間が明らかに異常(「時間ホットスポット」とも呼ばれる)な下流コンポーネントについてさらに調査します。本質的には「図に従って手がかりをたどる」(再帰法)アプローチであり、手がかりに従って段階的に掘り下げていき、根本原因となるコンポーネントに迫ります。
ターゲット調査法
過去の経験に基づいて、最も頻繁に異常が発生するコンポーネントを調査し、そのコンポーネントの主要なSLA指標を観測して異常があるかどうかを判断し、次に調査するコンポーネントを決定します。本質的には「除外法」(貪欲法)のアプローチであり、まず最も頻繁に異常が発生するコンポーネントを調査し、徐々に除外していくことで、根本原因となるコンポーネントに迫ります。
上図はデータベースアクセスリンクの簡略化された図です。注目すべき点は、上図の2つのコンポーネントがネットワークを介して相互にアクセスする場合、ネットワークもコンポーネントと見なすべきであるということです。2つのコンポーネント間のネットワークに異常が疑われる場合は、ネットワークリンク上の各レベルのスイッチを調査する必要があります。ODPのデプロイメント形態によっては、特にVPC間やクラウド間のネットワークアクセスなど、リンクが長い場合は、高度な注意を払う必要があります。
2つの調査手法に絶対的な優劣はなく、調査員は手元のツールの使い勝手と過去の調査経験に基づいて、最も効率的な手法を選択すべきです:
初めて稼働するビジネスリンクの場合、例えば一部の企業がハイブリッドクラウドデプロイメントモデルを採用し、一部のビジネスをオンプレミスデータセンターからパブリッククラウドに移行する場合、アクセスリンクがクラウドを跨いでいるため、ドリルダウン調査法を選択するのが適しています。
成熟したビジネスリンクで、その中の一部のコンポーネントに変更があった場合、例えば大規模なセールイベントやODPのアップグレードの場合、ターゲット調査法を選択するのが適しています。
上記のシナリオに基づいて調査手法を選択する方法に加えて、エラーメッセージに基づいてボトルネックコンポーネントを正確に特定する方法もあります。この方法は、調査員の経験に大きく依存します。
一般的なエラースタックは上図のようになります。スタックは3層に分かれており、OBServerとODPについては説明するまでもありませんが、アプリケーションサーバー部分について紹介します。アプリケーションは通常、データミドルウェアを通じてデータベース接続を管理し、アクセス認証、接続ウォームアップ、接続プール化などの機能を提供します。データミドルウェアは通常、パッケージ形式でアプリケーションに導入され、両者の運用ログは通常は分離されています。以下の本文中では、アプリケーションとデータミドルウェアを区別せず、統一してアプリケーション層と呼びます。
各層のコンポーネントのエラーは、自身の運用ログに出力されるだけでなく、上位層にスローされ、上位層のコンポーネントの運用ログにも出力されます。したがって、ある層でエラーメッセージが発生した場合、まずはどの層のエラーかを分析する必要があります。その層のコンポーネントがスローしたエラーであれば、その層から調査を開始します。下位層のコンポーネントがスローしたエラーであれば、直接対象層で調査を行うことができます。
以下の本文では、各層の一般的なエラーについて紹介します。なお、各層のエラーはその層で発生するだけでなく、上位層にスローされ、上位層の運用ログにも現れる可能性があることを説明しておく必要があります:
アプリケーションエラー
アプリケーションエラー「データベース接続プールがいっぱいです」
このエラーはアプリケーションシステムで最も一般的なエラーの一つであり、アプリケーションシステムのデータベース接続プールがいっぱいで、新しいリクエストが接続を取得できないことを示しています。アプリケーションコードは通常、トランザクションを開始してデータベースにアクセスします。トランザクション内では、データベースへのアクセス以外に、他のダウンストリームシステムへの呼び出しも発生します。例えば、ダウンストリームのアプリケーションシステムやキャッシュなどです。トランザクション開始時に接続プールから接続を取得し、トランザクション終了時に接続を接続プールに返却します。接続プールがいっぱいになるのは、通常、トランザクションの実行時間が長すぎるためです。トランザクションの実行時間が長くなる原因を調査する必要があります。これは、データベースリクエストのRTが高すぎることに加えて、他のダウンストリームシステムへのアクセス時間が長すぎる、アプリケーションシステム自体の問題などが原因である可能性があります。
他のダウンストリームシステムの処理時間が長すぎる:RPC呼び出しによるダウンストリームシステムへのアクセス時間が長すぎるため、トランザクション全体の時間が長くなります。データベースシステムへのアクセス時間は正常です。
アプリケーションシステム自体:アプリケーションシステム自体のfullgcやCPU使用率が暴走し、システムがフリーズすることで、トランザクション全体の時間が長くなります。データベースシステムへのアクセス時間は正常です。
アプリケーションエラー「データベース接続に失敗しました」
アプリケーションシステムがOBServerに接続に失敗したことを示しています。これは、バックエンドのデータベースシステムがリクエストでパンクし、接続確立に失敗した場合のほか、アプリケーションシステム自体の問題(例:fullgcの発生、アプリケーションサーバーのNIC異常、アプリケーション層のデータベース設定ミスなど)、またはアプリケーションサーバーとOBServer間のネットワーク異常などが原因である可能性があります。
アプリケーションエラー「ロック競合」
アプリケーションシステムが特定のデータベースオブジェクトにロックをかける際にロック競合が発生したことを示しています。アプリケーションシステムは通常、ロックメカニズム(悲観的ロックまたは楽観的ロック)を通じて、同一オブジェクトへの同時アクセスを制御します。ロック競合は強いアプリケーション意味を持ち、データベースシステムのRTが暴走し、アプリケーションシステムが大量にタイムアウトして再試行する場合以外に、アプリケーションシステム自体から原因を探る必要があります。例えば、スケジューリングシステムの異常により同一オブジェクトに対する大量の同時操作が発生したり、特定のハッキング攻撃が発生したりする場合などです。
OBProxyエラー
OBProxyエラー
ERROR 1317 (70100): Query execution was interruptedクライアントが積極的にクエリを中断したことを示しており、通常はクライアントが送信したSQLリクエストが想定されたタイムアウト時間内に返されなかった場合、またはユーザーが
Ctrl + Cを使用して積極的にKill Queryを実行した場合です。本番環境でこのエラーが多数発生する場合、アプリケーション側面から見たSQLの実行時間がクライアントのタイムアウト時間(Query Timeout)を超えていることを意味しており、クライアントからOBserverまでの各コンポーネントを調査する必要があります。
OBServerエラー
OBServerエラー
ERROR 4012 (HY000): Timeout, query has reached the maximum query timeoutSQLリクエストのOBServer内部処理時間がサーバー側のタイムアウト時間(
ob_query_timeout)を超えたことを示しており、OBServer内部に異常が存在すると直接特定できます。ob_query_timeoutはSQLの最大実行時間を設定するために使用され、単位はマイクロ秒です。この変数の詳細については、ob_query_timeoutを参照してください。
注意
上記で説明したように、エラーメッセージに基づいてコンポーネントを正確に特定する方法は、各コンポーネントのバージョンによって異なる場合があり、調査員の経験の蓄積に大きく依存します。調査員は、特定のバージョンに応じた一連の調査方法論を蓄積する必要があります。