MySQL 接続で認証失敗エラーが発生する場合の分析と解決方法

MySQL 接続で認証失敗エラーが発生する場合の分析と解決方法

[問題の説明]

アプリケーション側では、次のエラーが時々表示されます。

メソッド 'mysql_native_password' を使用してユーザー 'yyyy' のホスト 'xxxx' への認証に失敗し、次のメッセージが表示されました: ストリームからの読み取りに失敗しました。

パフォーマンス特性:

1. この問題は Connector/NET を使用する場合にのみ発生します。JDBC ドライバーを使用する場合は同様の問題は発生しません。

2. アプリケーション サーバーは複数ありますが、このエラーを報告するのは 1 つだけなので、サーバー側の問題は除外できます。

3. この問題は非常にランダムに発生するため、サーバー/IIS を再起動すると一時的に問題が解決する場合があります。

4. シナリオによっては、アプリケーション サーバーの CPU がそれほど高くなく、このエラーが時々発生することがあります。

クライアントは Windows マシン、ドライバーは MySQL Connector ADO.NET Driver for MySQL (Connector/NET)、使用するバージョンは比較的新しい 6.9.9 です。

詳しい分析と解決策を見てみましょう。

【問題分析】

アプリケーション サーバー側とデータベース側でパケットをキャプチャします。両側でキャプチャされたパケットは一貫しています。ネットワークの問題は除外できます。キャプチャされたパケットと時間ポイントは次のとおりです。

シリアルナンバー絶対時間相対時間(秒)ソース目的ネットワークパケットの内容
1 12:58:47 9.07アプリケーションサーバーデータベースサーバー......S.
2 12:58:47 9.07データベースサーバーアプリケーションサーバー…として。
3 12:58:47 9:07アプリケーションサーバーデータベースサーバー…あ…。
4 12:58:47 9:07データベースサーバーアプリケーションサーバー…AP通信…
5 12:58:47 9.27アプリケーションサーバーデータベースサーバー…あ…。
6 12:58:57 19.12データベースサーバーアプリケーションサーバー…あ…ふ
7 12:58:57 19.12アプリケーションサーバーデータベースサーバー…あ…。
8 12:59:10 32.00アプリケーションサーバーデータベースサーバー…AP通信…
9 12:59:10 32.00データベースサーバーアプリケーションサーバー…..R..

上記のネットワーク パケットの相互作用から判断すると、最初の 3 つのパケットは TCP の 3 ウェイ ハンドシェイク プロトコルです。問題は 6 番目のパケットにあります。データベース サーバーは、データベース接続を終了するために、アプリケーション サーバーに Finish パケットを送信します。データベースは接続がタイムアウトしたことを検出するため、Finish パケットを送信します。 これは、サーバー側の Connect_timeout 変数によって制御されます。その理由は、アプリケーションが 10 秒以上ネットワーク パケットをデータベース サーバーに送信していないためです。ネットワーク パケットの相互作用から判断すると、5 番目と 6 番目のパケット間の時間間隔はちょうど 10 秒です。

上記の正常なデータベース接続と異常なデータベース接続を比較します。 アプリケーション サーバーは、5 番目のパケットをデータベースに送信した後、すぐに次のネットワーク パケットをデータベースに送信する必要があります。このパッケージは主に、アカウント番号、ドライバーのバージョン、オペレーティング システムの情報などをデータベース サーバーに送信します。 [以下は通常のネットワーク パケットのスクリーンショットです]異常なエラーが発生した場合、クライアントはパケットの送信を遅延します。フレーム8で送信されます。この時点で、接続は完了しています。フレーム 9 では、データベースがアプリケーション サーバーにリセット パケットを送信し、接続を完全に終了します。

次に、クライアントがアカウント、ドライバーのバージョン、オペレーティング システムの情報をデータベースに送信するのになぜ時間がかかるのかを詳しく分析してみましょう。この部分のコードは、Connector/NET MySQLAuthenticationPlugin.cs ファイルにあります。 コードのこの部分を変更し、時間追跡を実行して問題をさらに特定します。以下は、時点別に印刷される追跡情報です。

トレースによれば、約30秒の操作遅延があります。 MySQLDefs::OSDetails が返される場合。コードのこの部分は次のとおりです。

[表示名("_os_details")]

パブリック文字列 OSDetails

{

得る

{

文字列 os = 文字列.Empty;

試す

{

var searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");

var コレクション = searcher.Get();

foreach (コレクション内の変数 mgtObj)

{

os = mgtObj.GetPropertyValue("キャプション").ToString();

壊す;

}

}

例外 ex をキャッチします { System.Diagnostics.Debug.WriteLine(ex.ToString()); }

os を返します。

}

}

このコードは、WMI クエリを通じてキャプション情報を取得します。つまり、オペレーティングシステムのバージョン情報です。これは WMI 呼び出しなので、多くの依存関係があります。

【問題検証】

このコードを抽出してみましょう。以下に短い再現コードを示します。

静的void Main(文字列[] 引数)

{

ストップウォッチ watch = new Stopwatch();

(真)

{

ウォッチを再起動します。

var searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");

var コレクション = searcher.Get();

foreach (コレクション内の変数 mgtObj)

{

文字列 os = mgtObj.GetPropertyValue("キャプション").ToString();

}

ウォッチを停止します。

Console.WriteLine(watch.ElapsedMilliseconds);

(watch.ElapsedMilliseconds >= 1000)の場合

{

Console.WriteLine("--------------");

File.AppendAllText("abc.txt", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") +","+ watch.ElapsedMilliseconds + "\r\n");

}

}

}

問題のあるアプリケーション サーバーで上記のコードを実行すると、WMI クエリがタイムアウトしたことがわかります。次のポイントは、30 秒以上をキャプチャしたポイントです。

2017-11-21 17:19:30.208, 33638

2017-11-21 17:20:09.193, 33199

2017-11-21 17:20:53.086, 33201

2017-11-21 17:27:05.114, 32976

2017-11-21 17:28:19.178, 33635

2017-11-21 17:30:07.130, 65977

2017-11-21 17:30:49.051, 40478

2017-11-21 17:31:15.126, 26072

2017-11-21 17:38:16.048, 66671

2017-11-21 17:38:49.204, 33152

2017-11-21 17:39:53.161, 33828

2017-11-21 17:40:38.121, 33549

2017-11-21 17:47:09.179, 33775

2017-11-21 17:47:57.174, 33164

【解決】

WMI クエリが遅くなる理由はいくつか考えられます。たとえば、オペレーティング システムの CPU 使用率が高い場合や、クエリ自体がデッドロックしている場合などです。この問題はさらなる分析が必要です。しかし、コードを見ると、この WMI クエリはオペレーティング システムに関する情報を取得するためだけのものであることがわかります。この情報はキャッシュできます。接続するたびに WMI クエリを実行する必要はありません。

エラーの根本的な原因は、MySQL C# コネクタでオペレーティング システム情報を取得するのに時間がかかりすぎるため、トリガー サーバーへの接続がタイムアウトになることです。この部分(長時間の操作を引き起こす可能性があります)をコメントアウトし、さらに検証を実行します。タイムアウト エラーは発生しません。

パブリック文字列 OSDetails
{
得る
{
dbglog.dolog("MysqlDefs::OSDetails1");
文字列 os = 文字列.Empty;
/*試す
{
var searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
var コレクション = searcher.Get();
foreach (コレクション内の変数 mgtObj)
{
os = mgtObj.GetPropertyValue("キャプション").ToString();
dbglog.dolog(String.Format("MysqlDefs::OSDetails::foreach{0}", os.ToString()));
壊す;
}
}
catch (例外 ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); }*/
dbglog.dolog("MysqlDefs::OSDetails2");
os を返します。
}
}

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。

以下もご興味があるかもしれません:
  • mysql_connect(): 古い (4.1.1 より前の) 認証プロトコルを使用した接続が拒否されました
  • MYSQL の「クライアントは認証をサポートしていません」の解決策
  • MySQL バージョン 4.1 以降に接続するときに発生する「クライアントが認証プロトコルをサポートしていません」という問題の解決方法

<<:  nohup /dev/null 2>&1 の使い方の詳しい説明

>>:  Centos7.6にTomcat-8.5.39をインストールする方法

推薦する

CSS3に基づいてiPhoneを描く

結果:実装コードhtml <div class='iphone'> &l...

Reactの親コンポーネントと子コンポーネント間のデータ転送の詳細な説明

目次1. 親コンポーネントが子コンポーネントにデータを渡す1.1. 親コンポーネントコード1.2. ...

CentOS7 で MySQL 5.7.24 をコンパイルしてインストールする詳細なチュートリアル

目次依存関係をインストールするブーストをインストールMySQLをコンパイルしてインストールする構成依...

Linux の sudo 脆弱性により不正な特権アクセスが発生する可能性がある

Linux で新たに発見された sudo の脆弱性を悪用すると、特定のユーザーが root としてコ...

一般的なDocker Composeコマンドの詳細な説明

1. Docker Compose の使用方法は docker コマンドの使用方法と非常に似ています...

Linuxカーネルのアクセス制御セキュリティを強化する方法

背景以前、当社のプロジェクト チームは、Windows、Linux、macOS の 3 つの主要なオ...

Webフロントエンド開発におけるエラーを見つけるための基本的な考え方

WEB開発は主に2つのインタラクション(B/Sデータ)から構成されますブラウザ: 1html、css...

ディレクトリスクロール効果を実現するネイティブJS

これはネイティブ JS で実装されたテキスト スクロール効果です。この効果は通常、ニュース、ダイナミ...

MySQL 入門 - SQL 実行プロセス

目次1. プロセス2. コアアーキテクチャ2.1 サーバー層の基本コンポーネントの紹介3. ステート...

Lvs+Nginx クラスターを使用して高並列アーキテクチャを構築する例

目次1. Lvsの紹介2. Lvs負荷分散モード2.1 NAT 2.2 ターン2.3 DRモード3....

Linux カーネル デバイス ドライバー 高度な文字デバイス ドライバーのメモ

/****************** * 高度な文字デバイス ドライバー ***********...

ノード スキャフォールディングを使用してトークン検証を実装するサーバーを構築する方法

コンテンツスキャフォールディングを使用してノードプロジェクトを素早く構築するデータベースとやり取りす...

RedHat 6.5/CentOS 6.5 に MySQL 5.7.20 をインストールするための詳細なチュートリアル

rpmインストールパッケージをダウンロードするMySQL公式サイト: https://dev.mys...

CSS3 列を使用したカード ウォーターフォール レイアウトを実装するためのサンプル コード

この記事では、カード ウォーターフォール レイアウトを実現するための CSS3 列のサンプル コード...

MySQL マルチマスターと 1 スレーブのデータバックアップ方法のチュートリアル

概要いずれかのデータベースに対する操作は他のデータベースに自動的に適用され、2 つのデータベースのデ...