Czy zwiększone opóźnienie sieci spowoduje blokady tabeli w MS SQL Server?

16

Jeśli wykonuję pojedyncze wywołanie bazy danych SQL Server za pośrednictwem sieci o dużym opóźnieniu, czy z powodu tego opóźnienia wystąpią blokady tabeli? Powiedzmy, że pytam o tabelę A o niektóre rekordy, a SQL Server musi zwrócić te dane w wolnej sieci - czy w tabeli A pojawi się blokada odczytu, gdy serwer wyśle ​​odpowiedź przez sieć, czy też SQL Server zwolni blokadę przed wysłaniem odpowiedź?

Czy odpowiedź byłaby różna w zależności od wielkości odpowiedzi? Gdyby po prostu zwrócił kilka KB w porównaniu do kilkuset MB, czy miałoby to znaczenie?

Utworzenie wyraźnej transakcji, uruchomienie zapytań i zamknięcie transakcji spowodowałoby oczywiście zablokowanie tabel, ponieważ czas trwania transakcji jest skorelowany z moim opóźnieniem.

Evan M.
źródło
O ile nie określisz nolockpodpowiedzi, zawsze będzie blokada . Opóźnienie określa tylko, jak długo zamek będzie trzymany.
Brandon
3
A nawet nolock, nadal będziesz się zamki
billinkc
@brandon Czy Microsoft udokumentował to gdziekolwiek? Moje wyszukiwania okazały się puste.
Evan M
1
@Brandon NOLOCK nie oznacza, co myślisz, że to znaczy.
Aaron Bertrand
3
@Brandon Unless you specify a nolock hint, there will always be a lock.<- oznacza to, że jeśli używasz nolock, może nie być blokad. Ja tylko wyjaśniłem.
Aaron Bertrand

Odpowiedzi:

15

Jeśli klient długo odbiera dane i z kolei wysyła do SQL Server potwierdzenie, że je otrzymał, SQL Server musi czekać, dlatego SQL Server nie zwolni blokad blokowanych przez zapytanie, chyba że otrzyma potwierdzenie od klienta.

To nie jest dokładne, zależy to od poziomu izolacji.

Domyślnie READ COMMITTEDblokady nie są wstrzymywane na czas wykonywania instrukcji. READ COMMITTEDnie zapewnia spójności odczytu na poziomie instrukcji, jedyną gwarancją jest to, że nie można odczytać niezaangażowanych danych. Blokada współdzielona jest pobierana i utrzymywana w celu odczytania wiersza, a następnie zwolniona.

Chyba że masz typy LOB.

Typy LOB, potencjalnie bardzo duże, nie mogą być buforowane. Blokada współdzielona musi zostać nabyta i utrzymana do czasu wypełnienia oświadczenia, co zasadniczo daje ci REPEATABLE READzachowanie w READ COMMITTED.

Jeśli wykonuję pojedyncze wywołanie bazy danych MSSQL w sieci o dużym opóźnieniu, czy z powodu tego opóźnienia wystąpią blokady tabeli?

Opóźnienie nie powoduje blokady stołu, nie. Jeśli jednak zostanie uzyskana blokada stołu, opóźnienie ją przedłuży.

Cytując kogoś, kto zna mechanikę tego lepiej niż ja ( @RemusRusanu ):

Wyniki są zwracane z powrotem do programu klienckiego w trakcie wykonywania. Gdy wiersze „bąbelkują” w górę drzewa wykonania, górny operator zwykle ma za zadanie zapisanie tych wierszy w buforach sieciowych i wysłanie ich z powrotem do klienta. Wynik nie jest najpierw tworzony w pamięci pośredniej (pamięci lub dysku), a następnie wysyłany z powrotem do klienta, zamiast tego jest odsyłany w trakcie tworzenia (w trakcie wykonywania zapytania). Odesłanie wyniku z powrotem do klienta jest oczywiście uzależnione od protokołu kontroli przepływu w sieci. Jeśli klient nie pobiera aktywnie wyniku (np. Przez wywołanie SqlDataReader.Read ()), to w końcu kontrola przepływu będzie musiała zablokować stronę wysyłającą (wykonywane zapytanie), a to z kolei zawiesi wykonanie pytanie.[źródło]

Tam, gdzie wyniki nie są zużywane tak szybko, jak SQL Server może je dostarczyć, czy to ze względu na klienta, czy sieć, obserwujemy ASYNC_NETWORK_IOkumulację oczekiwań. Powtórzmy, że nie wpłynie to na zdobywane blokady, tylko na czas ich trwania.

Mark Storey-Smith
źródło
9

Odpowiedź Marka rozwiała wiele moich nieporozumień, ale chciałem opublikować moje odkrycia po przetestowaniu tego za pomocą NetBalancer do emulacji opóźnień.

Mój komputer lokalny wywołał zdalny serwer SQL i wykonał zarówno SELECT, jak i INSERT na stole w ramach niewielkiej transakcji. Na zdalnej maszynie podłączyłem się do lokalnej instancji SQL i użyłem pętli WHILE, aby wielokrotnie iterować po tabeli sys.dm_tran_locks, szukając jakichkolwiek blokad w tabeli, z której modyfikowałem i czytałem. Zainstalowałem NetBalancer na serwerze i użyłem go do emulacji opóźnień sieciowych na połączeniu sieciowym serwera.

Oto, co znalazłem:

  • W przypadku instrukcji, które nie zwracają dużej ilości danych do klienta, opóźnienie nie ma wpływu na blokowanie. Zwracałem najwyżej kilkaset bajtów danych. Transakcja na moim komputerze miała 250 ms WAITFOR, który utrzymywał blokady, a kiedy zwiększałem opóźnienie sieci do 5000 ms, czas blokady pozostawał bliski 250 ms.
  • W przypadku instrukcji, które zwracają dużo danych, opóźnienie zdecydowanie wpływa na blokowanie Zwróciłem dziesiątki tysięcy wierszy z powrotem do klienta, a bez opóźnienia czas blokady był krótki. Kiedy zwiększyłem opóźnienie, blokady były kontynuowane, dopóki nie otrzymałem wszystkich danych.

Z tego wnioskuję, że opóźnienie nie ma znaczenia, dopóki dane mieszczą się w buforze sieciowym. Jeśli SQL musi umieścić dużo danych w buforze sieciowym, opóźnienie spowoduje, że bufor ten utworzy kopię zapasową, a SQL będzie utrzymywał blokady tabeli, dopóki nie umieści wszystkich wyników zapytania w buforze.

Evan M.
źródło
Ciekawe wyniki. Z jakim programem klienckim / biblioteką jest to?
James L
Dobry towar. Czy jest szansa, że ​​możesz poświęcić na to trochę więcej czasu i sprawdzić, czy możesz określić rozmiar wyniku, w którym to się dzieje?
Mark Storey-Smith
@ MarkStorey-Smith Nie sądzę, żebym mógł uzyskać dokładną wartość, która bez wątpienia różni się w zależności od maszyny. Z vircom.com/security/improve-sql-nic-performance wygląda na to, że jest to ustawienie na lokalnej karcie sieciowej, a ta na moim serwerze bazy danych została ustawiona na „auto”
Evan M
@James Właśnie użyłem SSMS na obu komputerach
Evan M
0

Jeśli wykonuję pojedyncze wywołanie bazy danych MSSQL w sieci o dużym opóźnieniu, czy z powodu tego opóźnienia wystąpią blokady tabeli?

Po uruchomieniu i zakończeniu zapytania przez SQL Server generuje wyniki, umieszcza je w buforze wyjściowym i wysyła do klienta, który następnie pobiera wynik z bufora wyjściowego. SQL Server nie zwolni blokad przechowywanych przez zapytanie, chyba że otrzymane zostanie potwierdzenie od klienta. Co może powodować blokowanie.

Edycja: Evan, możesz odwołać się do tego artykułu pomocy technicznej MS

W sekcji 3

Blokowanie spowodowane przez SPID, którego odpowiednia aplikacja kliencka nie pobrała wszystkich wierszy wyników do zakończenia

Po wysłaniu zapytania do serwera wszystkie aplikacje muszą natychmiast pobrać wszystkie wiersze wyników do zakończenia. Jeśli aplikacja nie pobierze wszystkich wierszy wyników, w tabelach można pozostawić blokady, blokując innych użytkowników. Jeśli używasz aplikacji, która transparentnie przesyła instrukcje SQL na serwer, aplikacja musi pobrać wszystkie wiersze wyników. Jeśli tak się nie stanie (i jeśli nie można tego skonfigurować), rozwiązanie problemu z blokowaniem może być niemożliwe. Aby uniknąć tego problemu, można ograniczyć źle działające aplikacje do bazy danych raportowania lub wspomagania decyzji.

Shanky
źródło
Dzięki za odpowiedź Shanky! Czy wiesz, czy jest to gdzieś udokumentowane?
Evan M
5
To nie jest poprawne.
Mark Storey-Smith
To prawda, wydaje się, że „aplikacja nie pobiera wszystkich wierszy wyników, w tabelach można pozostawić blokady, blokując innych użytkowników. Jeśli używasz aplikacji, która transparentnie przesyła instrukcje SQL na serwer, aplikacja musi pobrać wszystkie wiersze wyników. Jeśli tak się nie stanie (i jeśli nie można tego skonfigurować), rozwiązanie problemu z blokowaniem może być niemożliwe. Aby uniknąć tego problemu, możesz ograniczyć źle działające aplikacje do bazy danych raportowania lub wspomagania decyzji ”. Co więcej, mówiłem ogólnie. Można przeczytać tutaj support2.microsoft.com/kb/224453
Shanky
4
@Shanky Stwórz duży stół. SELECT *od niego w READ COMMITTEDjednym połączeniu SSMS, monitor blokuje się od drugiego. Ile kiedykolwiek zamków widzisz?
Mark Storey-Smith