SQL Azureを使用して開発をするときには、特にコネクション管理が重要になります。今回はSQL Azureにおけるコネクション管理が必要になる原因と影響、そして対応方法について説明します。
コネクション管理が必要になる原因
オンプレミスのSQL Serverと比べると、SQL Azureにはコネクションが切断される条件や事象が多く存在します。切断される条件や事象には、自分のアプリケーションに起因するものと、第三者のアプリケーションに起因するものと、SQL Azure側の事情に起因するものがあります。様々な条件や事象が存在するので、コネクションは切断される前提でアプリケーションを構築することになります。具体的な条件や事象について幾つか説明していきます。
第1回「SQL Azureとは何か」で、SQL Azureはクラウド上で提供されるリレーショナルデータベースで共有リソースモデルを採用していること、高可用性のために三重化されていることを紹介しました。
特定ユーザがリソースを占有した場合、同じ物理サーバを使用しているユーザに悪影響が出てしまう可能性があります。SQL Azureでは全ユーザが快適に使用できるように、一部ユーザによる占有が悪影響を及ぼすレベルになった場合、調整サービスによって強制終了させられます。
リソースを最適に保つために、リソースの使用は閾値以内に収める必要があります。リソース閾値は、Windows AzureサポートチームBlogで紹介されていますので、詳細はそちらを参照してください。ここでは、2つの閾値を紹介します。
1つめは、30分以上アイドル状態にあるコネクションは切断される点です。これは、コネクションプールで、アイドル状態にあるコネクションにも適用されます。SQL Azureとコネクションプールを使用しているアプリケーションで、最後の接続から30分経過した場合、コネクションが切断されてしまいます。しかし、切断された段階では例外などは通知されません。切断されたコネクションがコネクションプールから割り当てられ、そのコネクションを使用してSQLを実行した場合に初めて例外が発生します。
2つめは、単一トランザクションで使用することができるトランザクションログは1GBまでとなる点です。夜間バッチなどの処理時に、トランザクション粒度が大きくなりがちですので、特に注意が必要です。
また、全体最適を実現するために、データベースの使用状況に応じてホストするサーバを移動することもあります。また、障害発生時にもデータベースの移動が発生します。
コネクションが切断されることの影響
コネクションがSQL Azure側から強制切断されることで、アプリケーションにどのような影響が出るのでしょうか。
よく遭遇するエラーのひとつが、
A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An established connection was aborted by the software in your host machine.)
です。このエラーは、SqlClientがプールから無効なコネクションを取得したときに発生し、アプリケーションに返されます。コネクションプール上のコネクションは、ネットワークやSQL Azureで制限されて無効化され、結果的に、たとえば実行コマンドなどでSqlException例外が発生します。
また、Microsoft IT(※)がmicrosoft.com上のVideo ShowcaseをWindows Azureへ移行した事例(Microsoft IT Starts Migration of Microsoft.com to Windows Azure Platform)でも、影響が紹介されています。
コネクションが閉じられた場合、問題を解決するためにコネクションオブジェクトを閉じて、開くのにとても時間がかかります。場合によっては、数百ミリ秒から数秒かかることもあります。また、ごくまれに再接続に失敗することがあります。
コネクション切断への対応方法
.NET Framework4の信頼性に関する更新1の使用
2011年8月9日にマイクロソフトがリリースした「.NET Framework4の信頼性に関する更新1」を使用することで、SQL Azureでのコネクションプール起因のエラー発生を軽減させることができます。
この更新を適用することで、SqlClientがアプリケーションにプールを返す前に、プールのコネクションが無効化されていないかを確認するようになります。もしコネクションが無効の場合、SqlClientは単純にアプリケーションにコネクションを返す前に再接続処理をします。
この修正は、サーバのラウンドトリップを増やしません。代わりに、TCPレイヤでソケット状態を確認するので、速く効果的です。この改善により、SQL ServerとSQL Azureへの接続時に、接続に失敗する機会を減らすことができます。しかし、この修正は再接続処理の代わりになるわけではありません。特にSQL Azureに接続する場合、再接続処理の実装必要です。
再接続処理を実装する
例外処理で、コネクションを再接続するロジックを独自に実装することが考えられます。独自ロジックを実装する際には、参考ドキュメントで紹介しているwikiやブログが参考になります。Microsoft ITでは、再接続処理がまれに失敗することを前提に、再接続処理を複数回繰り返すコードを書いています。
Transient Fault Handling Framework for SQL Azureが、Enterprise Library 5.0 Integration Pack for Windows Azure - November 2011に取り込まれているようです。Enterprise Library 5.0を使用することも検討してみてください。
参考ドキュメント
- 1.Windows Azure デベロッパー サポート チーム ブログ
マイクロソフトのWindows AzureチームによるSQL Azureコネクションが切断される閾値を紹介。
- 2.サポート情報
SQL Azureコネクション管理機能が強化されたアップデートの紹介。
- 3.technet wikiの記事
SQL Azureのコネクション管理に関する記事です。一番情報量が多く、正確な情報が提供されています。
- 4.Microsoft ITの人が書いたBlog記事
Microsoft ITでVideo ShowcaseのWindows Azure platformへ移行した際に、考察したSQL Azureの再接続処理について紹介されています。サンプルコードも掲載されているので、参考になります。
- 5.MSDN Library
SQL Azureの再接続処理がEnterprise Libraryに取り込まれているようです。