„ Eskalacja blokady ” to sposób, w jaki SQL obsługuje blokowanie dużych aktualizacji. Kiedy SQL zmienia wiele wierszy, bardziej wydajne jest, aby silnik bazy danych przyjmował mniej, większych blokad (np. Całą tabelę), zamiast blokować wiele mniejszych rzeczy (np. Blokady wierszy).
Ale może to być problematyczne, gdy masz ogromny stół, ponieważ zablokowanie całego stołu może zablokować inne zapytania na długi czas. Na tym polega kompromis: wiele blokad o małej ziarnistości jest wolniejszych niż mniej (lub jeden) bloków gruboziarnistych, a posiadanie wielu zapytań blokujących różne części tabeli stwarza możliwość zakleszczenia, jeśli jeden proces oczekuje na inny.
Dostępna jest opcja na poziomie tabeli LOCK_ESCALATION
, nowość w SQL 2008, która umożliwia kontrolę eskalacji blokad. Domyślnie „TABELA” umożliwia eskalację blokad aż do poziomu tabeli. WYŁĄCZONE w większości przypadków zapobiega eskalacji blokady do całego stołu. AUTO zezwala na blokady tabeli, z wyjątkiem sytuacji, gdy tabela jest podzielona na partycje, w którym to przypadku blokady są stosowane tylko do poziomu partycji. Zobacz ten wpis na blogu, aby uzyskać więcej informacji.
Podejrzewam, że IDE dodaje to ustawienie podczas ponownego tworzenia tabeli, ponieważ TABLE jest ustawieniem domyślnym w SQL 2008. Zwróć uwagę, że LOCK_ESCALATION nie jest obsługiwany w SQL 2005, więc musisz go usunąć, jeśli próbujesz uruchomić skrypt na Instancja 2005. Ponadto, ponieważ TABLE jest wartością domyślną, możesz bezpiecznie usunąć ten wiersz podczas ponownego uruchamiania skryptu.
Należy również zauważyć, że w SQL 2005 przed obecnością tego ustawienia wszystkie blokady mogły eskalować do poziomu tabeli - innymi słowy, „TABELA” była jedynym ustawieniem w SQL 2005.
CREATE TABLE
ponieważ tabela jeszcze nie istnieje, więc nie ma nic do zablokowania.ALTER TABLE
instrukcje. NajpierwALTER TABLE ADD column
, potemGO
, potem drugiALTER TABLE SET LOCK_ESCALATION=TABLE
, potem drugiGO
. Tak więcLOCK_ESCALATION
jest ustawiana po dodaniu kolumny. Jaki jest sens tego ustawiania po fakcie? Te dwieALTER TABLE
instrukcje są opakowane w transakcję, ale kolumna jest dodawana przedLOCK_ESCALATION
ustawieniem. Myślę, że pójdę trochę dalej i napiszę inną odpowiedź.Możesz sprawdzić, czy musisz dołączyć instrukcję LOCK_ESCALATION do swojego skryptu, porównując tę wartość przed i po uruchomieniu głównej części skryptu:
W moim przypadku zmiana tabeli w celu usunięcia lub dodania ograniczenia nie wydaje się modyfikować tej wartości.
źródło
Odpowiedź Justina Granta wyjaśnia, co
LOCK_ESCALATION
ogólnie robi ustawienie, ale pomija jeden ważny szczegół i nie wyjaśnia, dlaczego SSMS generuje kod, który je ustawia. Szczególnie dziwnie wygląda to naLOCK_ESCALATION
to, że jest to ostatnia instrukcja w skrypcie.Zrobiłem kilka testów i oto moje zrozumienie tego, co się tutaj dzieje.
Krótka wersja
ALTER TABLE
Oświadczenie, że dodaje, krople lub zmienia kolumna domyślnie bierze schemat modyfikacji (SCH-M) blokady na stole, który nie ma nic wspólnego zLOCK_ESCALATION
ustawieniem tabeli.LOCK_ESCALATION
wpływa na zachowanie podczas blokowania oświadczenia DML (INSERT
,UPDATE
,DELETE
, etc.), a nie w trakcie DDL (ALTER
). Blokada SCH-M jest zawsze blokadą całego obiektu bazy danych, w tym przykładzie tabeli.Jest to prawdopodobne, skąd bierze się zamieszanie.
SSMS dodaje
ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)
instrukcję do swojego skryptu we wszystkich przypadkach, nawet jeśli nie jest to potrzebne. W przypadkach, gdy ta instrukcja jest potrzebna, jest dodawana w celu zachowania bieżącego ustawienia tabeli, a nie w celu zablokowania tabeli w określony sposób podczas zmiany schematu tabeli, która ma miejsce w tym skrypcie.Innymi słowy, tabela jest zablokowana blokadą SCH-M na pierwszej
ALTER TABLE ALTER COLUMN
instrukcji, podczas gdy cała praca związana ze zmianą schematu tabeli jest zakończona. To ostatnieALTER TABLE SET LOCK_ESCALATION
stwierdzenie nie ma na to wpływu. Wpływa jedynie przyszłych sprawozdań DML (INSERT
,UPDATE
,DELETE
, itd.) Dla tej tabeli.Na pierwszy rzut oka wygląda to tak, jakby
SET LOCK_ESCALATION = TABLE
miało to coś wspólnego z faktem, że zmieniamy całą tabelę (zmieniamy tutaj jej schemat), ale jest to mylące.Długa wersja
Podczas zmiany tabeli w niektórych przypadkach program SSMS generuje skrypt, który ponownie tworzy całą tabelę, aw niektórych prostszych przypadkach (takich jak dodanie lub usunięcie kolumny) skrypt nie tworzy ponownie tabeli.
Weźmy tę przykładową tabelę jako przykład:
Każda tabela ma
LOCK_ESCALATION
ustawienie, które jest ustawioneTABLE
domyślnie. Zmieńmy to tutaj:Teraz, jeśli spróbuję zmienić
Col1
typ w projektancie tabel SSMS, SSMS generuje skrypt, który ponownie tworzy całą tabelę:Możesz zobaczyć powyżej, że ustawia on
LOCK_ESCALATION
dla nowo utworzonej tabeli. SSMS robi to, aby zachować bieżące ustawienie tabeli. Program SSMS generuje ten wiersz, nawet jeśli bieżąca wartość ustawienia jestTABLE
wartością domyślną . Chyba tylko po to, aby być bezpiecznym i wyraźnym oraz zapobiec ewentualnym przyszłym problemom, jeśli w przyszłości to domyślne się zmieni. To ma sens.W tym przykładzie konieczne jest wygenerowanie
SET LOCK_ESCALATION
instrukcji, ponieważ tabela jest tworzona od nowa i jej ustawienie musi zostać zachowane.Jeśli spróbuję dokonać prostej zmiany w tabeli za pomocą projektanta tabel SSMS, takiej jak dodanie nowej kolumny, wówczas SSMS generuje skrypt, który nie odtwarza tabeli:
Jak widać, nadal dodaje
ALTER TABLE SET LOCK_ESCALATION
oświadczenie, chociaż w tym przypadku wcale nie jest potrzebne. PierwszaALTER TABLE ... ADD
nie zmienia aktualnego ustawienia. Chyba programiści SSMS uznali, że nie warto próbować ustalić, w jakich przypadkach toALTER TABLE SET LOCK_ESCALATION
stwierdzenie jest zbędne i generować je zawsze, tak dla bezpieczeństwa. Nie ma nic złego w dodawaniu tego stwierdzenia za każdym razem.Ponownie
LOCK_ESCALATION
ustawienie dotyczące całej tabeli jest nieistotne, gdy schemat tabeli zmienia się za pośrednictwemALTER TABLE
instrukcji.LOCK_ESCALATION
ustawienie wpływa tylko na zachowanie blokowania instrukcji DML, jak npUPDATE
.Na koniec cytat z
ALTER TABLE
, podkreśl mój:źródło