2009-06-19 10 views
14

Używamy bazy danych SQL Server 2005 (bez wersjonowania wierszy) z ogromną instrukcją select, i widzimy, że blokuje ona inne instrukcje z działania (zobacz, używając sp_who2). Nie zdawałem sobie sprawy, że instrukcje SELECT mogą powodować blokowanie - czy jest coś, co mogę zrobić, by to złagodzić?Instrukcje SELECT SQL Server powodują blokowanie

+0

Używasz wyższe poziomy izolacji przypadkiem, jak powtarzalność odczytu lub serializacji? Niektóre komponenty ADO i CLR mogą się przeszukiwać bez Twojej wyraźnej zgody ... Na czym polega zasób blokujący (klucz, zakres, tabela)? –

+0

Nie określam poziomu izolacji. Czy istnieje sposób sprawdzenia, jaki poziom izolacji jest w użyciu? –

+1

Tak, sprawdź sys.dm_exec_sessions. column_isolation_level column. –

Odpowiedz

27

SELECT może zablokować aktualizacji. Właściwie zaprojektowany model danych i zapytanie spowodują jedynie minimalne blokowanie i nie będą stanowić problemu. "Zwykle" z podpowiedź NOLOCK jest prawie zawsze złą odpowiedzią. Odpowiednią odpowiedzią jest dostrojenie zapytania tak, aby nie skanowało on wielkich tabel.

Jeśli zapytanie jest untunable następnie należy najpierw rozważyć SNAPSHOT ISOLATION level, drugi należy rozważyć użycie DATABASE SNAPSHOTS i ostatnia opcja powinna być zabrudzona CZYTA (i jest lepiej zmienić isolation level zamiast używać wskazówkę NOLOCK). Zauważ, że brudne odczyty, jak sama nazwa wskazuje, zwrócą niespójne dane (np. Twój całkowity arkusz może być niezrównoważony).

+1

Cytowałem to na inne pytanie: http://stackoverflow.com/questions/1018651/nolock-vs-transaction-isolation-level/1018676#1018676 –

+2

Nie zrozum mnie źle, doskonała odpowiedź, ale staram się nie mówić w absolutach, nie wiedząc nic o ich zastosowaniu i designie. Na przykład, co by było, gdyby Twoja aplikacja była aplikacją dla przedsiębiorstw z funkcją "Zapytanie"? Zgadnij, kto pisze twoje zapytanie? Do swojej bazy danych? Klient! Nie ma wystarczającej liczby indeksów! Stopień izolacji migawki? Ile osób jednocześnie uderza w twoje bazy danych? Ponieważ porozmawiajmy o zasobach z tą opcją !! Tak, tak, nieumyte masy, które nie są guru DB, muszą używać brudnej lektury! – JustLooking

+0

@JustLooking masz dobre punkty, ale myślę, że odpowiedź Remusa jest dobrą wskazówką - szczególnie. jego pierwszy argument, który wymaga podpowiedzi nolock jest coś złego w ogólnym projekcie lub kwerendie. A co z bazą danych, która korzysta z transakcji? Czy nie powinno to oznaczać, że należy unikać nolocka? Wygląda na to, że utworzyłoby to wiele niejasnych i trudnych do sprawdzenia błędów, ponieważ są one przerywane. – MorganTiley

14

Od documentation:

Shared (S) zamki pozwalają jednoczesnych transakcji czytać (SELECT) zasób pod pesymistycznym kontroli współbieżności. Aby uzyskać więcej informacji, zobacz Types of Concurrency Control. Żadne inne transakcje nie mogą modyfikować danych, podczas gdy w zasobach istnieją blokady. Shared (S) blokady zasobów są zwalniane, gdy tylko zakończy się operacja odczytu, chyba że poziom izolacji transakcji jest ustawiony na powtarzalny odczyt lub wyższy, lub wskazówka blokowania jest używana do zatrzymywania zamków shared (S) na czas trwania transakcji.

A shared lock jest kompatybilny z innym udostępnionym blokadą lub blokadą aktualizacji, ale nie z blokadą exlusive.

Oznacza to, że Twoje zapytania SELECT będą blokować zapytania o numer: UPDATE i i odwrotnie.

Zapytanie zostanie umieszczone tymczasowo, gdy odczytuje blok wartości z tabeli i usuwa go po zakończeniu odczytu.

Na czas istnienia blokady nie można nic zrobić z danymi w zablokowanym obszarze.

Dwa SELECT zapytań nigdy nie blokują się nawzajem (chyba że są one SELECT FOR UPDATE)

poziom SNAPSHOT izolacji można włączyć na swojej bazie danych i używać go, ale należy pamiętać, że to nie przeszkodzi UPDATE zapytań przed zablokowana przez SELECT zapytaniami (co wydaje się być twoim przypadkiem).

To jednak zapobiegnie blokowaniu zapytań SELECT przez UPDATE.

Należy również pamiętać, że SQL Server, w przeciwieństwie do Oracle, używa menedżera blokad i utrzymuje go na liście połączonej w pamięci.

Oznacza to, że pod dużym obciążeniem sam fakt umieszczenia i usunięcia blokady może być powolny, ponieważ połączona lista powinna sama być zablokowana przez wątek transakcji.

+1

Nie należy przyjmować szczegółów implementacji menedżera blokady SQL Servere. Dość powiedzieć, że * nie * jest połączoną listą. –

+0

Bardzo jasne wyjaśnienie zamków! Dzięki! –

+0

Czy istnieje sposób na obejście udostępnionego blokady w MySQL? Próbowałem użyć każdego dostępnego poziomu izolacji, ale żaden z nich nie uniemożliwiał blokowania zapytań aktualizacyjnych przez select (co jest moim przypadkiem). –

0

Można ustawić transaction level czytać Uncommitted

+0

Czy to nie to samo, co używanie (NOLOCK)? Tak naprawdę nie chcę iść w tym kierunku ... –

+0

Jest taki sam jak NOLOCK i jest odpowiedni dla zapytań tylko do odczytu. – Andomar

+2

Nie, nie jest w porządku dla zapytań tylko do odczytu, ponieważ NOLOCK może * tylko * być stosowany do zapytań tylko do odczytu, więc każdy problem, który ma (i ma dużo) dotyczy również "tylko do odczytu". Niezbilansowany raport na temat arkusza jest nadal "tylko do odczytu", ale nie jest poprawny. –

2

Aby wykonać brudny czyta można:

using (new TransactionScope(TransactionScopeOption.Required, 
new TransactionOptions { 
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted })) 
{ 
//Your code here 
} 

lub

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..." 

pamiętać, że trzeba pisać (NOLOCK) po każdym stole chcesz brudzić czytać

0

You może również dostać się do zakleszczenia:

"Zakleszczenia obejmujące tylko jeden stół" http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

i lub nieprawidłowe wyniki:

„Wybiera pod odczyt zatwierdzony i powtarzalne ZOBACZ może powrócić nieprawidłowych wyników”

http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return-incorrect-results.aspx