Soru TransactionScope, bazı makinelerde otomatik olarak MSDTC'ye mi tırmanıyor?


Projemizde, veri erişim katmanımızın bir işlemdeki eylemlerini gerçekleştirmesini sağlamak için TransactionScope'ları kullanıyoruz. Hedefliyoruz değil Son kullanıcılarımızın makinelerinde MSDTC servisinin etkin olmasını gerektirir.

Sorun, geliştiricilerin makinelerimizin yarısında, MSDTC devre dışıyken çalışabiliriz. Diğer yarısı onu etkinleştirmiş olmalı ya da "[SERVER] üzerindeki MSDTC kullanılamıyor" hata mesajı.

Gerçekten kafamı kaşımıyor ve beni ADO.NET işlem nesnelerine dayanan ev eğrilmiş TransactionScope benzeri bir çözüm için geri döndürmeyi düşünmemi sağladı. Görünüşte çılgınca - geliştiricimizin yarısında çalışan (ve artmayan) aynı kod yapar diğer geliştiricinin üzerine tırmandım.

Daha iyi bir cevap vermeyi umuyordum Bir işlemin neden DTC'ye iletildiğini izleme ama ne yazık ki değil.

İşte sorun neden olacak bir kod örneği, ikinci tırmandırmaya çalışır, ikinci bağlantıda tırmanmaya çalışır.Open () (ve evet, o zamanda açık başka bir bağlantı yoktur.)

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();
}

Gerçekten kazdık ve bunu çözmeye çalıştık. İşte üzerinde çalıştığı makineler hakkında bazı bilgiler:

  • Dev 1: Windows 7 x64 SQL2008
  • Dev 2: Windows 7 x86 SQL2008
  • Dev 3: Windows 7 x64 SQL2005  SQL2008

Geliştiriciler çalışmıyor:

  • Dev 4: Windows 7 x64, SQL2008  SQL2005
  • Dev 5: Windows Vista x86, SQL2005
  • Dev 6: Windows XP X86, SQL2005
  • Ev Bilgisayarım: Windows Vista Home Premium, x86, SQL2005

Bu sorunu çözmek için tüm makineleri, Microsoft Update'in sunduğu her şeyle tamamen yamalıyorum.

1. Güncelleme:

MSDN işlem yükseltme sayfası aşağıdaki koşulların bir işlemin DTC'ye iletilmesine neden olacağını belirtir:

  1. İşlemde tek fazlı bildirimleri desteklemeyen en az bir dayanıklı kaynak yer alır.
  2. İşlemde tek fazlı bildirimleri destekleyen en az iki dayanıklı kaynak bulunmaktadır. Örneğin, tek bir bağlantıya sahip olmak bir işlemin teşvik edilmesine neden olmaz. Ancak, veritabanına bir veritabanına ikinci bir bağlantı açtığınızda, System.Transactions alt yapısı, işlemdeki ikinci dayanıklı kaynak olduğunu algılar ve bir MSDTC işlemine iletir.
  3. İşlemi farklı bir uygulama alanına veya farklı bir işleme "marshal" etmek için bir talep başlatılır. Örneğin, işlem nesnesinin bir uygulama alanı sınırı boyunca serileştirilmesi. Işlem nesnesinin değeri, bir uygulama etki alanı sınırında (aynı işlemde bile) geçmek için yapılan herhangi bir girişim işlem nesnesinin serileştirilmesiyle sonuçlanır. İşlem nesnelerini, bir İşlemi parametre olarak alan uzak bir yöntemde bir çağrı yaparak geçirebilir veya uzak bir işlemle servis verilen bileşene erişmeyi deneyebilirsiniz. Bu, işlem nesnesini serileştirir ve bir işlemin bir uygulama etki alanında serileştirildiği zamanki gibi bir artışa neden olur. Dağıtılıyor ve yerel işlem yöneticisi artık yeterli değil.

# 3 yaşamadık. # 2 olmuyor çünkü bir seferde sadece bir tane bağlantı var ve aynı zamanda tek bir 'dayanıklı kaynak' var. # 1'in olmasının herhangi bir yolu var mı? Tek fazlı bildirimleri desteklememesine neden olan bazı SQL2005 / 8 yapılandırması?

Güncelleme 2:

Kişisel olarak herkesin SQL Server sürümleri - "Dev 3" aslında SQL2008 ve "Dev 4" aslında SQL2005 var. Bu, iş arkadaşlarıma bir daha asla güvenmememi öğretir. ;) Verilerdeki bu değişim nedeniyle, sorunumuzu bulduğumuzdan eminim. Bizim SQL2008 geliştiriciler sorun yaşamadık çünkü SQL2008 SQL2005'in sahip olmadığı muhteşem miktarlarda müthiş miktarlara sahiptir.

Ayrıca, TransactionScope'u kullandığımız gibi kullanabileceğimiz SQL2005'i destekleyeceğimizi ve TransactionScope'u kullanmak istiyorsak, etrafımızdaki tek bir SqlConnection nesnesini geçmemiz gerekeceğini ... SqlConnection'ın kolaylıkla geçemediği durumlarda sorunlu görünüyor ... sadece SqlConnection örneğinin kokuyor. Pew!

3'ü güncelle

Sadece soruya açıklık getirmek için:

SQL2008:

  • Tek bir TransactionScope içinde birden fazla bağlantıya izin verir (yukarıdaki örnek kodda gösterildiği gibi).
  • Caveat # 1: Bu çoklu SqlConnections iç içe geçmişse, yani iki veya daha fazla SqlConnections aynı anda açılırsa, TransactionScope hemen DTC'ye yükselecektir.
  • Caveat # 2: Farklı bir SqlConnection farklı bir şekilde açılırsa 'dayanıklı kaynak' (yani: farklı bir SQL Server), hemen DTC'ye iletilecek

SQL2005:

  • Tek bir TransactionScope içinde çok sayıda bağlantıya izin vermez, dönem. İkinci bir SqlConnection açıldığında / olduğunda yükselecektir.

4. Güncelleme

Bu soruyu daha da ileri götürmek adına karışıklık yararlı ve sadece daha fazla netlik için, SQL2005'i DTC'ye iletmek için nasıl tek  SqlConnection:

using (TransactionScope transactionScope = new TransactionScope()) {
   using (SqlConnection connection = new SqlConnection(connectionString)) {
      connection.Open();
      connection.Close();
      connection.Open(); // escalates to DTC
   }
}

Bu sadece bana kırılmış gibi görünüyor, ama sanırım her çağrı için SqlConnection.Open() bağlantı havuzundan yakalanıyor.

"Neden olsa bu olabilir?"  SqlTableAdapter, açılmadan önce bu bağlantıya karşı bir SqlTableAdapter kullanırsanız, SqlTableAdapter bağlantıyı açar ve kapatır, sizin için işlemi başarıyla tamamlar, çünkü şimdi yeniden açamazsınız.

Yani, temel olarak, TransactionScope'u SQL2005 ile başarılı bir şekilde kullanabilmek için, ilk TransactionScope'un noktasından açık kalan bir tür küresel bağlantı nesnesine ihtiyaç duyulmadığı sürece ulaşmanız gerekir. Genel bağlantı nesnesinin kod kokusunun yanı sıra, önce bağlantıyı açmak ve son olarak kapatmak, mümkün olduğunca geç bir bağlantı açma mantığına ve mümkün olan en kısa zamanda kapatmaya ters düşmektedir.


268
2017-11-06 22:24


Menşei


"Ortam işlemine dahil olabilecek veya bulunamayan diğer şeyleri burada yapın" ifadesini genişletebilir misiniz? Şüphesiz, orada ne var, kodun nasıl davrandığını büyük ölçüde etkiler? - RichardOD
"# 2, bir seferde yalnızca bir bağlantı olduğu için gerçekleşmiyor" - # 2, aynı bağlantının aynı anda açık olması gerektiğini, ikinci bağlantının aynı zamanda açık olması gerektiğini söylemiyor. - Joe
Güncellemenin yalnızca tek bir SqlConnection ile nasıl ortaya çıkabileceğini gösteren 4 Güncellemesi ile ilgili geri bildirimleriniz için teşekkür ederiz. Tam olarak, sadece tek bir SqlConnection kullanılmasının dikkatlice yapılmasına rağmen, tam olarak çalıştığım şey bu. Benim için deli olan bir bilgisayar olduğunu bilmek güzel. :-) - Oran Dennison
Bağlantı havuzu açısından, eğer birden fazla bağlantımız varsa (ve gerekirse iç içe geçiyorsak) birer birer açılıp kapanıyorsak, 1 gerçek bağlantı havuzu kaynağı veya bağlantı başına 1 kullanıyoruz, bunu belirlemek için bunu rasyonelleştirmeye çalışıyorum Uygun şekilde kapsamlandırılan "şekillendirilebilir" bağlantı yapıp yapmadığımı (kaçınmak istediğim) - brumScouse
Aynı işlem kapsamındaki iç içe bağlantılar, dağıtılmış bir işlem için teşvik edecektir. SQL Server 2008'den ve aynı işlem kapsamındaki çoklu (iç içe geçme) bağlantılardan, dağıtılmış bir transaksiyona teşvik edilmeyecektir. - PreguntonCojoneroCabrón


Cevaplar:


SQL2008 çoklu kullanabilir SQLConnectioniçinde bir TransactionScope tırmanmadan, bağlantıların aynı anda açık olmaması koşuluyla, birden çok "fiziksel" TCP bağlantısına neden olacak ve dolayısıyla eskalasyon gerektirecektir.

Bazı geliştiricilerin SQL2005 ve diğerleri SQL2008 olduğunu görüyorum. Hangisinin ilerlediğini ve hangilerinin doğru olmadığını belirlediğine emin misin?

En belirgin açıklama, SQL 2008 ile geliştiricilerin tırmanmayanlar olması.


68
2017-11-07 14:44



Evet, detaylar doğru ve kodlara bakacak olan var mı? İşlem kapsamında iki bağlantı vardır, ancak zaman içinde tek bir andan itibaren tek bir anlatan ve açılan tek bir bağlantı vardır. Ayrıca, hayır, çalışan makinelerde DTC çalışmıyor. - Yoopergeek
"Ancak, zaman içinde tek bir andan itibaren tek bir anda aniden tek bir bağlantı kuruldu" - neden bu konuyla ilgili? SQL2005 ile, bir işlem kapsamı içinde birden fazla bağlantı açarsanız, aynı anda açık kalmaya devam edip etmeyeceğinizi ileteceksiniz. Bunu düşündüğünüzde mantıklı olanı. - Joe
Siz ve hwiechers şimdi bana ikinci bir tahminim var ve pazartesi çalışmaya başlamaya ve bireysel makinelerini daha yakından inceledim ve SQL Server sürümlerinin daha önce bildirildiği gibi olduğundan emin oluyorum. - Yoopergeek
Siz ve hükmü haklısınız. Yüzümün her tarafında yumurta var. Bana ipucu ile vurduğun için teşekkür ederim. :) Çünkü ilk sizdiniz, cevabı aldınız. Yine de bir nokta açıklama eklemek isterim - SQL2008 birden fazla bağlantının açılmasına izin veriyor, ancak aynı anda değil. Herhangi bir zamanda sadece tek bir bağlantı açık olabilir veya TransactionScope DTC'ye yükselecektir. - Yoopergeek
@Yoopergeek "Aynı zamanda değil" in önemli olduğunu doğruladı ve @Joe 'nin cevabını buna göre düzenledim. Test sırasında TCP bağlantılarının izlenmesi, bağlantıların aynı anda kullanılmadığı durumlarda eski TCP bağlantısının yeniden kullanılacağını ve dolayısıyla TransactionScope tek bir şey yapabilir COMMIT Sunucu tarafında, tırmanmayı gereksiz hale getirecek. - Eugene Beresovsky


Konuyla ilgili araştırmamın sonucu:

enter image description here

Görmek Dağıtılmış İşlemlere İstenmeyen Eskalasyondan Kaçının

Hala Oracle’ın tırmanma davranışını araştırıyorum: Aynı DB'ye çok sayıda bağlantı içeren işlemler DTC'ye iletiliyor mu?


51
2018-03-23 07:15



Araştırmanızı paylaştığınız için teşekkür ederiz. Gerçekten yardımcı oldu. Bir daha hızlı sorgu. TransactionScope () ve sqlConnection.BeginTransaction () arasındaki fark nedir? - Baig
Buna göre özellik isteğiODAC 12C şimdi aynı veri kaynağına ardışık bağlantılar kullanırken dağıtımı teşvik etmeyecek şekilde SQL 2008 olarak davranmalıdır. - Frédéric


Bu kod irade 2005'e bağlanırken tırmanmaya neden olur.

MSDN'deki belgelere bakın - http://msdn.microsoft.com/en-us/library/ms172070.aspx

SQL Server 2008'de Promotable İşlemleri

.NET Framework'ün 2.0 sürümünde   ve SQL Server 2005, bir saniye açılıyor   TransactionScope içinde bağlantı   otomatik olarak   tam dağıtılmış bir işlem   işlem, her iki bağlantı da olsa   aynı bağlantı kullanıyorlardı   Teller. Bu durumda dağıtılmış   işlem gereksiz ek yük ekler   Bu performansı azaltır.

SQL Server 2008 ile başlayarak ve   .NET Framework'ün 3.5 sürümü,   yerel işlemler artık yok   dağıtılmış işlemlere terfi   başka bir bağlantı açılırsa   önceki işlem   işlem kapalı. Bu gerektirir   eğer kodunuzda değişiklik yok   zaten bağlantı havuzu kullanmak ve   işlemlerde yer almak.

Neden Dev 3: Windows 7 x64, SQL2005 başarılı ve Dev 4: Windows 7 x64 başarısız açıklayamıyorum. Bunun başka bir yol olmadığından emin misin?


31
2017-11-07 17:33





Bu cevabın neden silindiğini bilmiyorum ama bunun bazı ilgili bilgileri var gibi görünüyor.

17:42 'de Aug 4 '10 cevapladı Eduardo

  1. Set = False Enlist işlem sırasında otomatik listelemeyi önlemek için bağlantı dizesinde.

  2. Bağlantıyı katılımcılar olarak manuel olarak kaydet işlem kapsamı [orijinal makale modası geçmiş] veya bunu yapın: Otomatik MSDTC promosyonu nasıl önlenir?   [Archive.is]


8
2017-10-09 13:31



msdn.microsoft.com/en-us/library/ms172153%28v=VS.80%29.aspx bulunamadı, Visual Studio 2005 Emekli belgeleri - Kiquenet


İç içe bağlantı sorun ise çok emin değilim. Yerel bir SQL Server örneğini arıyorum ve DTC oluşturmuyor mu?

    public void DoWork2()
    {
        using (TransactionScope ts2 = new TransactionScope())
        {
            using (SqlConnection conn1 = new SqlConnection("Data Source=Iftikhar-PC;Initial Catalog=LogDB;Integrated Security=SSPI;"))
            {
                SqlCommand cmd = new SqlCommand("Insert into Log values(newid(),'" + "Dowork2()" + "','Info',getDate())");
                cmd.Connection = conn1;
                cmd.Connection.Open();
                cmd.ExecuteNonQuery();

                using (SqlConnection conn2 = new SqlConnection("Data Source=Iftikhar-PC;Initial Catalog=LogDB;Integrated Security=SSPI;Connection Timeout=100"))
                {
                    cmd = new SqlCommand("Insert into Log values(newid(),'" + "Dowork2()" + "','Info',getDate())");
                    cmd.Connection = conn2;
                    cmd.Connection.Open();
                    cmd.ExecuteNonQuery();
                }
            }

            ts2.Complete();
        }
    }

2
2018-05-13 15:56



Hangi SQL Server sürümünü kullanıyorsunuz? MePol Meinl'in cevabının 2008R2 ve / veya Denali'de yapılan değişiklikleri yansıtacak şekilde güncellenmesi gerekip gerekmediğini merak ediyorum. - Yoopergeek
SQL Server 2008 R2 kullanıyorum. - Iftikhar Ali
2008 R2'nin daha iyi davranıp davranmadığını merak ediyorum. @hwiechers'ın cevabı ayrıca, derlediğiniz Framework'ün sürümünün tırmanmayı önleyip önlemediğini merak ediyor. Son olarak, yerel bir R2 örneği olmanın herhangi bir fark yaratıp yaratmadığını merak ediyorum. 2008 R2 ve SQL Server 2012'nin piyasaya sürülmesiyle bunun nasıl değiştiğini araştırmak için zaman / kaynak sahibi olsaydım. - Yoopergeek
İç içe bağlantının sorun olup olmadığından emin değil misiniz? lol ... iyi çiçeklenme o zaman kaldırın !, neden dünya üzerinde insanlar kesinlikle gerekli değil, deyimleri kullanarak yuva yapmak, asla bilmeyeceğim. - Paul Zahra


İçinde 1'den fazla bağlantı kullanıyorsanız, TransactionScope her zaman DTC işlemine geçer. Yukarıdaki kodun DTC devre dışıyken çalışabilmesinin tek yolu, iki kez de bağlantı havuzundan aynı bağlantıyı almanızın büyük bir şansıdır.

"Sorun, geliştiricilerimizin yarısında, MSDTC devre dışı bırakılabilir." Engellendiğinden emin misin?)


1
2017-11-07 00:28