TCP キャッシュの過負荷による MySQL 接続中断のケーススタディ

MySQL 自体以外の他の要因がターゲットになる可能性をどのように分析すればよいでしょうか?

著者: Gong Tangjie は、ACOS DBA チームのメンバーで、主に MySQL の技術サポートを担当しており、MySQL、PG、および国内データベースを得意としています。

Aikeson オープンソース コミュニティによって作成されているため、オリジナルのコンテンツを許可なく使用することはできません。転載する場合は編集者に連絡し、出典を明記してください。

この記事は約 1,200 ワードで、読むのに 3 分かかると予想されます。

背景

バッチ タスクの実行中に、アプリケーションで問題が発生しました。一部のタスクのデータベース接続が突然失われ、その結果、タスクを完了できなくなりました。データベースのエラーログから、クライアントとサーバー間の通信が異常に中断されたことを示す「Aborted connection」情報が見つかりました。

分析する

問題の原因を突き止めるために、まず経験に基づいて、接続が中止される可能性のあるいくつかの一般的な状況を分析しました。

  1. クライアントは接続を適切に閉じず、mysql_close()関数を呼び出しませんでした。
  2. クライアントのアイドル時間がwait_timeoutまたはinteractive_timeoutパラメータの秒数を超えると、サーバーは自動的に切断します。
  3. クライアントが送受信したパケットのサイズがmax_allowed_packetパラメータの値を超えたため、接続が中断されました。
  4. クライアントがデータベースにアクセスしようとしましたが、権限がないか、間違ったパスワードが使用されているか、接続パケットに正しい情報が含まれていません。

ただし、調査の結果、上記の状況はいずれも現在の問題には当てはまらないことが判明しました。タスクは以前は正常に実行されており、プログラムは変更されていないため、最初の状況は除外できます。 MySQL のタイムアウト パラメーターを確認したwait_timeoutところ、interactive_timeoutどちらも 28800 (8 時間を超える) であり、タスクの実行時間を大幅に超えていることがわかりました。そのため、2 番目の状況は除外できます。また、max_allowed_packetクライアントとサーバーのパラメーターを確認したところ、両方とも 64M であり、この制限を超える可能性は低いことがわかりました。そのため、3 番目の状況は除外できます。また、クライアントのデータベース アクセス権、パスワード、接続パッケージ、その他の情報がすべて正しいことも確認しているため、4 番目の状況は除外できます。

現時点では、MySQL レベルには問題はないはずで、問題は別の場所にある可能性があると考えています。

問題をさらに特定するために、サーバーの関連するカーネル パラメータの一部を次のように変更しようとしました。

net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 120
net.core.rmem_default = 2097152
net.core.wmem_default = 2097152
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_syn_backlog = 16384

これらのパラメータは主に、ネットワーク接続のパフォーマンスと安定性を最適化し、接続が予期せず閉じられたりタイムアウトになったりするのを回避するためのものです。しかし、修正結果は改善されず、依然として接続が異常切断されてしまいます。

最後に、 Wiresharkツールを使用してパケット キャプチャ分析を試みたところ、サーバーがクライアントに大量の ACK パケットを送信するという異常な現象が見つかりました。以下に示すように:

これらの ACK パケットは、TCP プロトコルの確認パケットであり、サーバーがクライアントのデータ パケットを受信したことを示し、クライアントにデータの送信を続けるように要求します。しかし、なぜサーバーはこれほど多くの ACK パケットを送信するのでしょうか?ネットワークに異常が発生し、クライアントがサーバーから返されたACKパケットを受信できなくなった可能性があるため、サーバーはタイムアウトするかクライアントからの応答を受信するまで繰り返しACKパケットを送信すると考えられます。ただし、ネットワーク担当者による調査の結果、明らかな問題は見つかりませんでした。

パケット キャプチャの分析を続けると、別の異常な現象が発見されました。クライアントが送信サーバーにいくつかのウィンドウ警告を与えるということです。以下に示すように:

これらのウィンドウ警告は、TCP プロトコルのフロー制御メカニズムであり、サーバーまたはクライアントの受信ウィンドウがいっぱいで、これ以上データを受信できないことを示します。

[TCP Window Full] は、送信側から受信側に送信されるウィンドウ警告で、データ受信側の制限に達したことを示します。

[TCP ZeroWindow]は、受信側から送信側に送信されるウィンドウ警告で、受信側の受信ウィンドウがいっぱいであるため送信を一時的に停止することを送信者に伝えます。

上記の情報に基づいて、問題の原因は次のとおりであると推測します。MySQL が送信する必要があるデータが大きすぎるため、クライアントの TCP キャッシュがいっぱいになり、クライアントが TCP 内のデータをダイジェストするのを待つ必要があります。データの受信を続行する前にキャッシュを実行します。ただし、この期間中、MySQL はクライアントにデータの送信を継続するよう要求し続けます。クライアントが一定時間 (デフォルトは 60 秒) 以内に応答しない場合、MySQL はデータの送信がタイムアウトしたと見なし、接続を中断します。

この推測を検証するために、MySQL の低速ログを確認したところ、 Last_errno: 1161のレコードが多数見つかりました

これらのレコードは、MySQL がデータ送信時にタイムアウト エラーに遭遇し、その発生数がアプリケーションが失敗したタスクの数に非常に近いことを示しています。 MySQL 公式 Web サイトによると、このエラーの意味は次のとおりです。

エラー番号: 1161;シンボル: ER_NET_WRITE_INTERRUPTED; SQLSTATE: 08S01

メッセージ: 通信パケットの書き込みでタイムアウトが発生しました

これはネットワーク書き込みが中断されていることを意味しており、これを制御するパラメータが MySQL レベルにあるため、net_write_timeout パラメータを 600 に変更してみてください。バッチ タスクは正常に実行されます。

したがって、MySQL 接続が異常に中断される理由は、クライアントが取得したデータベースが大きすぎて、クライアントの TCP キャッシュを超えているためです。この間、クライアントはまずキャッシュ内のデータを処理する必要があります。クライアントはデータの送信を続行しましたが、クライアントは 60 秒以内に応答できなかったため、MySQL がデータの送信をタイムアウトして接続を中断しました。

結論は

上記の分析と試みを通じて、次の結論に達しました。

  • パケット キャプチャ情報には、クライアントのキャッシュがいっぱいでサーバーに時間内にフィードバックできないため、大量の ACK 情報が含まれています。そのため、サーバーは 60 秒 (net_write_timeoutデフォルト値は 60) を超えるまで繰り返し ACK 情報を送信し、 MySQL を使用して接続を中断します。
  • 実際にMySQLでSQLが実行されているため、遅いログにはLast_errno:1161のレコードが多くありますが、クライアントにデータを送信する際にデータ量がクライアントのTCPキャッシュを超えたため、クライアントアプリケーションが処理しませんでした。データが 60 秒以内にキャッシュに保存されると、クライアントにデータを送信するときに MySQL がタイムアウトになります。
  • MySQL レベルでパラメータを調整することnet_write_timeoutによってのみこの現象を軽減できます。根本的な原因は、1 つの SQL によって取得されるデータの量が大きすぎて、アプリケーションがキャッシュ内のデータを短時間で処理できないことです。これにより、後続のデータ送信がタイムアウトになります。

最適化の提案

  • データはビジネス レベルでバッチ処理され、単一の SQL クエリがサーバーから大量のデータを取得して、クライアント側の TCP キャッシュが不十分になることを回避します。
  • MySQL のパラメータを増やすnet_write_timeoutか、クライアントの TCP キャッシュを増やすことでこの状況を軽減できますが、データが多すぎると依然としてパフォーマンスと安定性に影響を与えるため、問題を完全に解決することはできません。
  • SQL ステートメントを最適化して、LIMIT、WHERE、その他の条件を使用したり、集計関数やグループ化関数などを使用したりして、不要なデータの戻りを削減し、データ量を削減してクエリの効率を向上させます。

さらに技術的な記事については、https: //opensource.actionsky.com/をご覧ください。

SQLEについて

SQLE は、開発環境から運用環境までの SQL 監査と管理をカバーする包括的な SQL 品質管理プラットフォームです。主流のオープンソース、商用および国内データベースをサポートし、開発、運用および保守のためのプロセス自動化機能を提供し、オンライン効率を向上させ、データ品質を向上させます。

SQL取得

タイプ 住所
リポジトリ https://github.com/actiontech/sqle
書類 https://actiontech.github.io/sqle-docs/
リリースニュース https://github.com/actiontech/sqle/releases
データ監査プラグイン開発ドキュメント https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse
ライナスは、カーネル開発者がタブをスペースに置き換えることを阻止するために自ら問題を解決しました。 彼の父親はコードを書くことができる数少ないリーダーの 1 人であり、次男はオープンソース テクノロジー部門のディレクターであり、末息子は中核です。ファー ウェイ: 一般的に使用されている 5,000 のモバイル アプリケーションを変換するのに 1 年かかった Java はサードパーティの脆弱性が最も発生しやすい言語です。Hongmeng の父: オープンソースの Honmeng は唯一のアーキテクチャ上の革新です。中国の基本ソフトウェア分野で 馬化騰氏と周宏毅氏が握手「恨みを晴らす」 元マイクロソフト開発者:Windows 11のパフォーマンスは「ばかばかしいほど悪い」 老祥基がオープンソースであるのはコードではないが、その背後にある理由は Meta Llama 3 が正式にリリースされ、 大規模な組織再編が発表されました
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/actiontechoss/blog/11054532