Troubleshooting Connectivity #9 – ローカル接続でネットワーク エラーとはこれいかに?


 

高橋 理香

SQL Developer Support Escalation Engineer

みなさん、こんにちは。

皆さんの疑問にお答えするブログを書きたいと思い早数年、今回は時々お問い合わせされる方が声にされる「SQL Server が稼動している環境上のほかのアプリケーションやツールから接続した場合にもネットワーク エラーが発生するのはなぜ?」について、その接続の仕組みなどを説明したいと思います。

前提: ローカル接続でトランスポートネットワークエラーが発生する事象について疑問があるとはどういうこと?

まず、以下の2つの図を比べてみましょう。

image

図1 ではクライアント マシン CLIENT01 上の SQL Server Management Studio (以降、SSMS) から物理的にネットワークの回線を介してリモート マシン SERVER01 上で動作する SQL Server に接続するイメージです。接続でエラーが発生するということは、接続のリクエストとその完了の通信経路上で遅延や障害があった場合に生ずるため、図1 のパターンにおいてネットワークに起因した問題があればネットワーク通信におけるエラーが返される可能性があるということは容易に想像できますね。

それでは図2 はいかがでしょう。サーバー マシン SERVER01 上で SSMS を起動し、同じ SERVER01 上で動作する SQL Server に接続するイメージです。この場合、物理ネットワーク回線を介さないはずです。それにもかかわらずネットワーク層のエラーが発生することがある、これが「ローカル接続なのにネットワーク エラーが発生するのはなぜ?」という疑問です。

実際にどちらの構成であっても次のようにネットワークに問題があるようにも見えるエラーが発生します。

SERVER01 に接続できません。 ADDITIONAL INFORMATION:

SQL Server への接続を確立しているときにネットワーク関連またはインスタンス固有のエラーが発生しました。サーバーが見つからないかアクセスできません。インスタンス名が正しいこと、および SQL Server がリモート接続を許可するように構成されていることを確認してください。 (provider: TCP Provider, error: 0 – リモート コンピューターによりネットワーク接続が拒否されました。) (Microsoft SQL Server、エラー: 1225)

リモート コンピューターによりネットワーク接続が拒否されました。

SQL Server への接続の仕組み

SSMS 等のアプリケーションやツールから SQL Server までにはどのように接続のリクエストが処理されるのでしょうか。Troubleshooting Connectivity #1 で説明したように、SQL Server に接続する場合には最初に OS レベルのセッションを確立する必要があります。たとえば TCP/IP プロトコルを使った接続の場合には、TCP/IP のセッションを確立します。そこで、SSMS から SQL Server に TCP/IP セッションを確立する仕組みを例にあげてみましょう。

SSMS は主に .NET Framework で開発されたアプリケーションであり、最初のダイアログにおける接続では内部的に .NET Framework Data Provider for SQL Server (System.Data.SqlClient) を使用しています。System.Data.SqlClient では SQL Server との通信を行う処理を SQL Server Network Interface (SNI) 層で管理しており、この SNI 層では OS レベルのセッションの確立やログイン処理などを Windows OS で利用可能な Windows Sockets (Winsock 関数) を利用して実現しています。たとえばダイアログからの接続時には SqlConnection.Open というメソッドを呼び出しますが、このメソッドが呼ばれると SNI 層では Winsock の connect 関数を呼び出すことになります。そして、SNI 層ではこの connect 関数の結果を踏まえ、次のログイン処理へ進むか、エラーとして処理するかなどの判断、および、必要な処理を行います。

では、「SSMS から TCP/IP プロトコルを使用して SQL Server に接続する」という動作に関して、リモート接続時とローカル接続時で違いはあるのでしょうか。

基本的な違いはありません。接続先がリモートであってもローカルであっても、SNI 層では Winsock 関数を呼び出し、接続処理を行います。正確には、SNI 層では接続に使用するプロトコルを選択する機能も持つため、接続先がローカルの場合には特にプロトコル指定がない限り共有メモリ プロトコルを使用するなど、接続先がローカルかリモートかの判別は行っています (*)。しかし、それでも Winsock 関数を呼び出す点に違いはありません。そのため、Winsock 関数による通信上の問題があると判断される限り、それはネットワーク層におけるエラーとして扱われます。これがローカルでもネットワーク関連のエラーがあるとメッセージとして表面化する理由です。

なお、上記動作は ODBC ドライバーや OLE DB プロバイダーでも同様です。MDAC や Windows DAC に含まれる ODBC ドライバー等では SNI ではなく、ネットワーク ライブラリと呼ばれていましたが、基本的に同様の仕組みとなっています。

// (*) 補足 – クラスタ環境のローカル接続

接続先がローカルかリモートかは接続文字列に指定した接続先サーバー名が現在そのプロセスが動作しているホスト名と同一かどうかによって判断しています。SNI 層では同一であると判断した場合に共有プロトコルを優先的に使用し、接続試行します。クラスタ環境の場合には、接続先はクラスタ名\インスタンス名となり、稼動ノード名とは異なるため、ローカルであるとは判断されません。そのため、ローカル接続でも TCP/IP もしくは名前付きパイプが使用されます。

ローカル接続失敗の一般的な原因

基本的には Troubleshooting Connectivity #2 で説明した主な原因と同一です。ただし、ローカル接続の OS レベルのセッション確立においてはネットワーク インターフェース カード (NIC) の外に通信が及ぶことはない (*) ため、ネットワーク負荷などの物理ネットワーク回線に関する要因が除外されます。

過去のお問い合わせでローカル接続失敗の要因として多いのはやはりサーバーの高負荷ですが、このような負荷が高い場合においては、同一マシン上で動作するプロセスの優先度に差がある (sqlservr.exe が高でアプリケーション プロセスが通常、もしくは、sqlservr.exe は通常でアプリケーション プロセスが低) 場合において、優先度により CPU をすぐに利用できずに待たされることで、接続のリクエストに遅延が生じ、タイムアウトするというケースがあります。負荷が高い場合にバッチ処理で接続タイムアウトが発生するようなケースがあったら、優先度の設定を確認してみてはいかがでしょう。

 

// (*) 補足 – ローカル接続での NIC 外への通信

セッション確立後のログイン認証においては、Windows 認証のために Active Directory への問い合わせが必要となります。Windows 認証の場合に接続タイムアウト エラーが発生し、SQL Server 認証では発生しない場合には、ネットワーク通信遅延が疑われます。SQL Server のセキュリティ設定で SQL Server 認証を許容している場合には切り分けとして試してみるとよいでしょう。

 

 

ローカル接続におけるネットワーク関連エラーについて参考になりましたでしょうか。少しでもイメージいただけたならうれしいです。

過去の Troubleshooting Connectivity シリーズはこちら。 Troubleshooting Connectivity #1 – SQL Server への接続

Troubleshooting Connectivity #2 – エラー情報からわかる失敗原因

Troubleshooting Connectivity #3 – 予期しない接続切断

Troubleshooting Connectivity #4 – 接続エラーの調査方法

Troubleshooting Connectivity #5 – セッション確立までの動作

Troubleshooting Connectivity #6 – 接続タイムアウトは悪なのか?

Troubleshooting Connectivity #7 – 接続タイムアウトエラーまでの時間は?

Troubleshooting Connectivity #8 – エラー番号からわかる接続失敗原因:エラー 26

clip_image001

Comments (0)

Skip to main content