2009-11-18 7 views
6

Właśnie zaczynam pracę z wykorzystaniem TransactionScope, okazuje się, że zawsze są nieoczekiwane rzeczy, które napotykam na zawsze, aby debugować.Common Gotchas podczas korzystania z TransactionScope i MS DTC

Uważam, że posiadanie ich skonsolidowanej listy byłoby znakomite w przypadku tych "dziwnych błędów" oraz poszerzyło naszą wiedzę o dziwności na platformie.

Niektóre kontekst, w jaki sposób mam zamiar używać zakresów transakcji:

  • aplikacji internetowych
  • wielu serwerów WWW, serwerów aplikacji i serwerów SQL
  • transakcje będą głównie transakcje bazy danych, ale niektóre będą podniesiony, by pisać do MSMQ.

Odpowiedz

3

2 rzeczy z mojej głowie:

  • transakcje zostaną podwyższone podczas korzystania z więcej niż jednego obiektu połączenia w takim samym zakresie, nawet jeśli połączenia mają taką samą ConnectionString (ta jest stała w sql 2008). Czytaj więcej w this thread i dbconnectionscope rozwiąże ten problem na SQL 2005
  • msdtc przypadki muszą być w stanie zobaczyć siebie i muszą mieć swoje bezpieczeństwo poprawnie skonfigurowany http://support.microsoft.com/kb/899191 (pozwalają przychodzące i wychodzące, nie wymagają wzajemnego uwierzytelniania jest zwykle najbezpieczniejszy zakład). Użyj DTCPing do rozwiązywania problemów z połączeniem między dtc przypadkach jak wyjaśniono tutaj: http://support.microsoft.com/kb/306843

Chcesz transakcje być lekka jak najwięcej, DTC wprowadza wiele napowietrznych. Ty też chcesz, aby transakcje były jak najkrótsze, więc wprowadzaj je tylko na serwerach aplikacji, a nie na serwerze WWW. Przeskakuj przez sieć między serwerami aplikacji i bazą danych tak mało, jak to tylko możliwe i tak szybko, jak to możliwe, przesyłaj ruch sieciowy między serwerami sieci Web i aplikacjami za pośrednictwem innego połączenia niż między serwerami aplikacji i bazą danych, a ostatnią z nich wywołaj szybko , absurdalnie krótkie połączenie.

Jeśli masz wiele serwerów aplikacji, możesz rozważyć utworzenie pojedynczego wystąpienia programu msdtc na serwerze (np. W bazie danych lub na jednym z serwerów aplikacji) i używać tego zdalnie ze wszystkich serwerów aplikacji zamiast z każdego z uruchomionych własne, ale nie wiem, jakie to dodatkowe korzyści.

+1

Naprawdę jest naprawiony w SQL Server 2008? Korzystam z SQLS2008, a gdy otworzę drugie połączenie z tym samym ciągiem połączenia, transakcja otrzyma rozproszony identyfikator GUID. Więc ... czy to tylko po stronie klienta, czy tak naprawdę staje się transakcją rozproszoną? – Triynko

+0

Zobacz http://msdn.microsoft.com/en-us/library/ms172070%28VS.90%29.aspx Nie przetestowałem tego dla siebie, ale według dokumentów powinien być przynajmniej prawdopodobny scenariusz gdzie sql 2008 zachowuje się w ten sposób. Być może pomocne może być zmodyfikowanie połączenia, aby wyraźnie kontrolować łączenie. – stombeur

+1

Wygląda na to, że nie został rozwiązany z SQL Server 2008, widząc transakcję podniesioną do DTC z tym samym ciągiem połączenia i lokalną bazą danych – mamu

-2

Jeśli używasz programu SQL Server i sprawdzasz transkcję @@, będzie to 0, nawet jeśli masz aktywny TransactionScope.

+1

To nie będzie zero; Właśnie to przetestowałem. Prawdopodobnie otwierasz połączenie przed zakresem transakcji, co oznacza, że ​​twoje połączenie nie uczestniczy w ogóle w transakcji (coś, czego się właśnie nauczyłem, zobacz mój post tutaj: http://stackoverflow.com/questions/2884863/under-what -ciscstances-is-an-sqlconnection-automatycznie-dołączone-do-otoczenia/2886326 # 2886326). Otwórz połączenie w zasięgu transakcji lub jawnie zarejestruj swoją istniejącą transakcję w zasięgu, wywołując połączenie.EnlistTransaction (Transaction.Current). Uruchom "select @@ transcount", aby zobaczyć jego niezerową wartość. – Triynko

1

Należy również pamiętać, że jeśli zmienisz którykolwiek z obiektów podczas transakcji, nie zostaną one wycofane, chyba że dodasz kod do obsługi tego.

Zobacz TransactionScope and rolling back object state

+0

Co? Jeśli mówisz o obiektach bazy danych, to nie jest to prawda. Jeśli wydajesz polecenia w połączeniu zarejestrowanym w zakresie transakcji i nie zatwierdzasz go, wówczas gdy zakres zostanie usunięty, zmiany zostaną wycofane ... tak jak każda inna transakcja. Jeśli mówisz o obiektach innych niż bazy danych, takich jak pliki i zmienne aplikacji, to tak ... ponieważ nie mają one nic wspólnego z transakcją. – Triynko

+0

Miałem bardzo dziwne zachowanie podczas używania 'TransactionScope' i DDL - musiałem pozbyć się' TransactionScope' i użyć normalnych, jawnych transakcji, aby to naprawić. – Lucero

0

Mam nadzieję, że to pomoże komuś jeden dzień:

Jeśli masz TransactionScope z wielu operacji SQL wewnątrz, DTC nie będzie zaangażowany warunkiem

  1. użyć identyczne ciąg połączenia dla każdego połączenia
  2. połączenia nie są zagnieżdżone.

tj. otwórz, zrób coś, zamknij. otwórz, zrób coś, zamknij.

Teraz dla Gotcha: jeśli kiedykolwiek to zrobić w procesie (w innym wątku)

SqlConnection.ClearAllPools()

i że dzieje się między dwoma procesami - DTC będzie zaangażowany natychmiast. Jeśli nie masz uruchomionego DTC, wygeneruje wyjątek.

Powiązane problemy