2013-02-28 25 views
15

Rozwiązywanie problemów z rodzajem struktury synchronizacji między dwiema bazami danych SQL Server, na oddzielnych serwerach (obydwa SQL Server 2008 Enterprise 64 bity SP2 - 10.0.4000.0), poprzez połączone połączenia z serwerem, a my doszliśmy do punktu, w którym utknęliśmy.Wartość SQL MIN_ACTIVE_ROWVERSION() nie zmienia się przez długi czas

Logika określająca, które rekordy są "oczekujące na synchronizację", jest oczywiście oparta na wartościach ROWVERSION, w tym z użyciem MIN_ACTIVE_ROWVERSION(), aby uniknąć brudnych odczytów.

Wszystkie operacje SELECT są enkapsulowane w SP po każdej stronie "źródła". Jest to schemat próbka jednego SP:

PROCEDURE LoaderRetrieve(@LastStamp bigint, @Rows int) 
    BEGIN 
    ... 
    (vars handling) 
    ... 

    SET TRANSACTION ISOLATION LEVEL SNAPSHOT 

    Select TOP (@Rows) Field1, Field2, Field3 
    FROM Table 
    WHERE [RowVersion] > @LastStampAsRowVersionDataType  
    AND [RowVersion] < @MinActiveVersion 
    Order by [RowVersion] 

    END 

podejście działa dobrze, zwykle zsynchronizować zapisy z oczekiwanym tempie 600k/h (Job każde 30 sekund, wielkość partii = 5k), ale w pewnym momencie , proces synchronizacji nie znajduje żadnego pojedynczego rekordu do przesłania, mimo że istnieje kilka tysięcy rekordów o wartości ROWVERSION większej niż parametr @LastStamp.

Sprawdzając przyczynę, stwierdziliśmy, że wartość parametru MIN_ACTIVE_ROWVERSION() ma wartość mniejszą niż (lub nieco większą, tylko 5 lub 10) od przeszukania szukanego @LastStamp. To oczywiście nie powinno być problemu, ponieważ podejście MIN_ACTIVE_ROWVERSION() został wprowadzony w celu uniknięcia problemów brudny odczyt i tylne, BUT:

Problem widzimy w niektórych przypadkach, podczas wystąpienia powyższego scenariusza jest to, że wartość MIN_ACTIVE_ROWVERSION() nie zmienia się podczas długiego (naprawdę długiego) okresu, np. 30/40 minut, czasem więcej niż jedną godzinę. Ta wartość jest znacznie mniejsza niż wartość @@DBTS.

Po raz pierwszy pomyśleliśmy, że było to związane z oczekującą transakcją DB jeszcze nie zatwierdzoną. Zgodnie z MSDN definicji o MIN_ACTIVE_ROWVERSION() (link):

Zwraca najniższą wartość rowversion aktywny w bieżącej bazie danych. Wartość rowversion jest aktywna, jeśli jest używana w transakcji, która nie została jeszcze zatwierdzona:.

Ale podczas sprawdzania sesji (sys.sysprocesses) z open_tran > 0 podczas trwania tej kwestii, nie mogliśmy znaleźć żadnego sesja z waittime większej niż kilka sekund, tylko jeden lub dwa występujące +/- 5 minut waittime sesji.

W tym momencie staramy się zrozumieć sytuację: MIN_ACTIVE_ROWVERSION() nie zmienia się w długim okresie czasu, a w tym okresie nie znaleziono niezatwierdzonych transakcji z długim czasem oczekiwania.

Nie jestem DBA i może być tak, że brakuje nam czegoś na zdjęciu, aby przeanalizować ten problem, a niektóre badania na forach i blogach nie mogą znaleźć żadnej innej wskazówki. Do tej pory open_tran> 0 było uzasadnionym powodem, ale w okolicznościach, które ujawniłem, jest jasne, że jest coś jeszcze i nie wiem dlaczego.

Wszelkie uwagi są mile widziane.

+3

+1 za tak dobrze napisane pytanie. Zamiast dodawać rozwiązanie do pytania, dodaj je jako odpowiedź. – Kermit

+6

@luiggig: Rozwiązania - nawet przez Ciebie - powinny być publikowane jako odpowiedzi. Możesz dodać tę część jako odpowiedź. A potem zaakceptuj to, jeśli nikt inny nie wymyśli lepszego. –

Odpowiedz

6

Cóż, w końcu znajduję rozwiązanie po kopaniu trochę więcej.

Problemem jest to, że szukaliśmy sesji z długim waittime, ale real deal było znalezienie sesje, które mają aktywną partię Od jakiegoś czasu.

Jeśli jest sesja, w której open_tran = 1, aby uzyskać dokładnie od kiedy ta transakcja jest otwarta (i oczywiście nadal aktywna, jeszcze nie zatwierdzona), pole Last_batch z sys.sysprocesses zostanie zaznaczone.

Korzystanie z tej kwerendy:

select 
    batchDurationMin= DATEDIFF(second,last_batch,getutcdate())/60.0, 
    batchDurationSecs= DATEDIFF(second,last_batch,getutcdate()), 
    hostname,open_tran,* from sys.sysprocesses a 
    where spid > 50 
    and a.open_tran >0 
    order by last_batch asc 

moglibyśmy zidentyfikować sesję z otwartym tran bycia aktywnym ponad 30 minut. A dzięki wartościom hostów i kilku innym kontrolom w serwisach internetowych (a także przy użyciu dbcc inputbuffer) znaleźliśmy odpowiedzialny proces.

Tak więc ostateczne pytanie brzmi: "rzeczywiście istnieje aktywna sesja z niezapowiedzianą transakcją", dlatego MIN_ACTIVE_ROWVERSION() nie ulega zmianie. Szukaliśmy tylko procesów o złych kryteriach.

Teraz, gdy wiemy, który proces zachowuje się w ten sposób, następnym krokiem będzie poprawienie go.

Mam nadzieję, że wyniki przydadzą się komuś innemu.