.NET Framework 4.6.1 is now available! でアナウンスされた内容となりますが、現在の System.Data.SqlClient や Microsoft.Data.SqlClient には、ConnectRetryCount というオプションが追加されており、接続文字列で再接続の回数を調整することができるようになっています。
サポートされるバージョンについては、
等に記載されているのですが、SQL Server 2014 以降または、Azure の PaaS の SQL Server ベースの環境でサポートされる機能となります。
リトライについては、ライブラリ側で実装されていると思うのですが、SQL Server のバージョンがどのように ConnectRetryCount に再接続と関係しているか、把握できていなかったので、軽く調べてみました。
ConnectRetryCount を SQL Server 2012 以前のバージョンで使用しても、接続後の再接続は行われません。
現在の .NET Framework では、ConnectRetryCount の初期値は 1 になっていますので、1 回は再接続が行われる設定となっています。
しかし、SQL Server 2012 への接続に対して、System.Data.SqlClient の BID トレース を取得してみると次のようなトレースとなっており、接続が切断されている場合には、再接続が行われずエラーとなっています。
SQL Server 2019 に接続して同様の動作を行った場合は次のようになります。
ConnectRetryCount をサポートしている場合には、「SNICheckConnection」により、接続の状態がチェックされ、切断されている場合は再接続が行われ、後続の処理が実行されていることが確認できます。
これはネットワークレベルでも同様の操作となっており、接続に使用しているポートが RST によりリセットされた場合、2012 ではそのまま処理が終わりますが、2014 以降の場合は RST のパケットを受け取った場合、再接続が行われ後続の処理が実行されます。
ライブラリレベルで ConnectRetryCount をサポートしているというものもちろん必要となりますが、ConnectRetryCount を使用することができるためには、サーバーの Token Stream のレスポンスとして、「FEATUREEXTACK」が含まれており、「SessionRecovery」のオプションが設定されていることも必要となります。
SQL Server 2019 であれば、接続後のレスポンスに次のようなデータがが含まれています。
2012 に接続した場合は次のようなレスポンスとなっており、Token Stream は受け取っているのですが、その中には「FEATUREACK」が含まれていません。
「FEATUREACK」については TDS のドキュメントの 2.2.7.11 FEATUREEXTACK で解説されています。
再接続に使用される「SESSIONRECOVERY」については、次のように記載されており、TDS 7.4 で含まれた内容となります。
SQL Server で使用される TDS のバージョンについては、6 Appendix A: Product Behavior で記載されています。
SQL Server 2012 も TDS 7.4 を使用しているのですが、2012 では、FEATUREEXTACK がサポートされていないようで、7.4 の中でもバージョンによって挙動が違う箇所が出てきていますね。
「Microsoft.Data.SqlClient」 での実装としては次のような箇所となるかと思います。(System.Data.SqlClient も同様だと思いますが細かくは見れていません)
- https://github.com/dotnet/SqlClient/blob/main/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs#L2317
- https://github.com/dotnet/SqlClient/blob/main/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs#L2532
- https://github.com/dotnet/SqlClient/blob/d600f8921e193c72b37d728b8a76cee2cfece9ac/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs#L1451
これらの箇所で FEATUREEXTACK の判断がされています。(_sessionRecoveryAcknowledged が true になっているかどうかがポイントなのかと)
どうやって SQL Server のバージョンを判断しているのかが気になったのですが、SQL Server のバージョンで判断しているのではなく「FEATUREEXTACK」のレスポンスを確認しており、このレスポンスが含まれるのが SQL Server 2014 以降というようになっているようですね。