[解決済み】一部のマシンでTransactionScopeが自動的にMSDTCにエスカレートする?
質問
私たちのプロジェクトでは、データアクセス層がトランザクション内でアクションを実行することを保証するためにTransactionScopeを使用しています。私たちの目標は ではなく は、エンドユーザーのマシンで MSDTC サービスが有効になっている必要があります。
問題は、開発者の半分のマシンでは、MSDTCを無効にしたまま実行できることです。 残りの半分はMSDTCを有効にしなければなりません。 MSDTC on [SERVER] is unavailable" のエラーメッセージが表示されます。
ADO.NETのトランザクションオブジェクトをベースにしたTransactionScopeのような自作のソリューションに戻そうかと真剣に悩んでいます。開発者の半数で動作している(そしてエスカレートしていない)同じコードで、そのようなことができるなんて、正気の沙汰とは思えません。 は もう一人の開発者のものではエスカレートしてしまうのです。
に良い回答があればと思いました。 トランザクションがDTCにエスカレートされた理由を追跡する が、残念ながらない。
以下はトラブルの原因となるコードのサンプルで、エスカレーションしようとするマシンでは、2番目のconnection.Open()でエスカレーションしようとします(そう、その時は他の接続は開いていないのです)。
using (TransactionScope transactionScope = new TransactionScope() {
using (SqlConnection connection = new SqlConnection(_ConStr)) {
using (SqlCommand command = connection.CreateCommand()) {
// prep the command
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()) {
// use the reader
connection.Close();
}
}
}
// Do other stuff here that may or may not involve enlisting
// in the ambient transaction
using (SqlConnection connection = new SqlConnection(_ConStr)) {
using (SqlCommand command = connection.CreateCommand()) {
// prep the command
connection.Open(); // Throws "MSDTC on [SERVER] is unavailable" on some...
// gets here on only half of the developer machines.
}
connection.Close();
}
transactionScope.Complete();
}
私たちは本当に掘り下げて、これを解明しようとしました。 以下、動作するマシンについての情報です。
- Dev 1: Windows 7 x64 SQL2008
- Dev 2: Windows 7 x86 SQL2008
- 開発環境3:Windows 7 x64 <ストライク SQL2005 SQL2008
動作しないデベロッパー
- Dev 4: Windows 7 x64, <ストライク SQL2008 SQL2005
- Dev 5: Windows Vista x86, SQL2005
- 開発環境6:Windows XP X86、SQL2005
- 自宅PC:Windows Vista Home Premium, x86, SQL2005
なお、問題を突き止めるために、すべてのマシンにマイクロソフト・アップデートで提供されているすべてのパッチを適用しています。
アップデート1:
- http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/a5462509-8d6d-4828-aefa-a197456081d3/ は、2006年当時、同じような問題について述べています。
- http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope%28VS.80%29.aspx - このコードサンプルを読むと、DTCにエスカレートするネストされたセカンド接続(実際にはセカンドSQLサーバーへの接続)が明確に示されていることがわかります。 私たちのコードでは、このようなことはしていません - 異なるSQLサーバーや接続文字列を使っているわけでもなく、ネストされたセカンダリー接続を開いているわけでもありません。 DTCにエスカレーションされることはないはずです。 .
- http://davidhayden.com/blog/dave/archive/2005/12/09/2615.aspx (2005年版)では、SQL2000に接続するとDTCへのエスカレーションが必ず発生することを説明しています。 私たちはSQL2005/2008を使用しています。
- http://msdn.microsoft.com/en-us/library/ms229978.aspx トランザクションのエスカレーションに関するMSDN。
そのMSDNのtransaction-escalationのページには、以下の条件でトランザクションがDTCにエスカレーションされると書かれています。
- 単相通知をサポートしない耐久性のあるリソースが少なくとも1つ、トランザクションに登録されていること。
- 単相通知をサポートする少なくとも2つの耐久性のあるリソースがトランザクションに登録されています。例えば、1 つの接続を参加させても、トランザクションは昇格しません。ただし、データベースへの 2 つ目の接続を開いてデータベースが参加するたびに、System.Transactions インフラストラクチャは、それがトランザクション内の 2 つ目の耐久性のあるリソースであることを検出し、それを MSDTC トランザクションにエスカレートさせます。
- 異なるアプリケーションドメインまたは異なるプロセスへのトランザクションをマーシャルする要求が呼び出される。例えば、アプリケーションドメインの境界を越えたトランザクションオブジェクトのシリアライズ。トランザクション・オブジェクトはmarshaled-by-valueであり、アプリケーション・ドメインの境界を越えて渡そうとすると(同じプロセスであっても)、トランザクション・オブジェクトのシリアライズが行われることを意味する。トランザクションオブジェクトを渡すには、Transactionをパラメータとして受け取るリモートメソッド上で呼び出しを行うか、リモートトランザクションサービスコンポーネントにアクセスしようとすることができる。これはトランザクションオブジェクトをシリアライズし、アプリケーションドメイン全体でトランザクションがシリアライズされるときのようなエスカレーションをもたらす。分散され、ローカルのトランザクション・マネージャはもはや適切ではありません。
3.は発生していません。#なぜなら、一度に接続されるのは1つだけであり、それも単一の「耐久性のあるリソース」に対してだからです。 1が起こる可能性はありますか? SQL2005/8の設定により、単相通知がサポートされていないのでしょうか?
更新2:
個人的に全員のSQL Serverのバージョンを再調査したところ、"Dev 3"は実はSQL2008で、"Dev 4"は実はSQL2005だったのだそうです。 これでもう二度と同僚を信用しないようになったよ(笑)。 このデータの変化から、私たちは問題を発見したと確信しています。 SQL2008の開発者は、SQL2005にはない素晴らしい機能が大量に含まれているため、この問題を経験していないのです。
また、SQL2005をサポートすることになったので、今までのようにTransactionScopeを使うことができず、TransactionScopeを使いたければ、単一のSqlConnectionオブジェクトを受け渡す必要があるということです... SqlConnectionを簡単に受け渡すことができない状況では問題があると思われます... グローバルSqlConnectionインスタンスの臭いがします。 ピュー!
アップデート3
ここまでの質問ではっきりさせたいのですが
SQL2008です。
- 1つのTransactionScope内で複数の接続を可能にする(上記サンプルコードで実証済み)。
- 注意点1:複数のSqlConnectionsがネストされている場合、つまり2つ以上のSqlConnectionsが同時に開かれた場合、TransactionScopeは直ちにDTCにエスカレートします。
- 注意点2:別のSqlConnectionが、異なる '耐久性のあるリソース' (例: 別の SQL Server) は直ちに DTC にエスカレートします。
SQL2005です。
- 1 つの TransactionScope 内で複数の接続を許可しない。 2つ目のSqlConnectionが開かれた場合、エスカレートします。
更新情報4
この問題をより深く理解するために
<ストライク
めちゃくちゃ
SQL2005でDTCにエスカレートさせる方法を説明します。
シングル
SqlConnection
:
using (TransactionScope transactionScope = new TransactionScope()) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
connection.Close();
connection.Open(); // escalates to DTC
}
}
これは私には壊れているとしか思えませんが、もしすべての
SqlConnection.Open()
は、接続プールから取得します。
"なぜこのようなことが起こるのでしょうか。 接続を開く前に SqlTableAdapter を使用すると、SqlTableAdapter は接続を開いて閉じ、トランザクションを効果的に終了します。
つまり、基本的に SQL2005 で TransactionScope をうまく使うには、最初の TransactionScope がインスタンス化されてから不要になるまで開いたままの、ある種のグローバル接続オブジェクトが必要なのです。 グローバル接続オブジェクトのコード臭さに加え、接続を最初に開いて最後に閉じるというのは、接続をできるだけ遅く開き、できるだけ早く閉じるというロジックと相反するものです。
解決方法は?
SQL Server 2008 では、複数の
SQLConnection
を1つの
TransactionScope
この場合、複数の物理TCP接続が発生し、エスカレーションが必要になります。
開発者の中には、SQL Server 2005を使用している人と、SQL Server 2008を使用している人がいるようですね。どれがエスカレートしてどれがエスカレートしないか、正しく認識できていますか?
最も明白な説明は、SQL Server 2008を使用している開発者が、エスカレーションしていない開発者であるということでしょう。
関連
-
[解決済み] [Solved] 1つ以上のエンティティで検証に失敗しました。詳細は'EntityValidationErrors'プロパティを参照してください [重複]。
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】ここで「要求URIに一致するHTTPリソースが見つかりませんでした」となるのはなぜですか?
-
[解決済み] [Entity Framework 4.1でエンティティに関連オブジェクトを追加する際に、エンティティオブジェクトをIEntityChangeTracker.の複数のインスタンスから参照できない。
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】Unity3DでOnTriggerEnterが動作しない件
-
[解決済み】クロススレッド操作が有効でない。作成されたスレッド以外のスレッドからアクセスされたコントロール
-
[解決済み】C# - パスに不正な文字がある場合
-
[解決済み】Visual studio 2019がデバッグ時にフリーズする件
-
[解決済み】ランダムなブーリアンを生成する最速の方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】指定されたキャストが有効でない?
-
[解決済み] エンティティタイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】C#で四捨五入する方法
-
解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C# [解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C#.
-
[解決済み】リソースの読み込みに失敗した:ステータス500(内部サーバーエラー)のサーバーの応答)
-
[解決済み】WPFでXamlファイルにコメントを追加する方法は?
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み] 関数を終了するには?
-
[解決済み】Nullableオブジェクトは値を持たなければならない?