LATCH_EX Oczekuje na zasób METADATA_SEQUENCE_GENERATOR


11

Mamy proces, który generuje raport asortymentowy. Po stronie klienta proces dzieli konfigurowalną liczbę wątków roboczych, aby utworzyć fragment danych dla raportu, który odpowiada jednemu z wielu sklepów (potencjalnie tysiące, zwykle dziesiątki). Każdy wątek roboczy wywołuje usługę sieci Web, która wykonuje procedurę przechowywaną.

Proces bazy danych do przetwarzania każdego fragmentu gromadzi wiązkę danych do tabeli #Temporary. Na końcu każdej porcji przetwarzania dane są zapisywane w stałej tabeli w tempdb. Wreszcie na koniec procesu jeden wątek po stronie klienta żąda wszystkich danych ze stałej tabeli tempdb.

Im więcej użytkowników uruchamia ten raport, tym wolniej się robi. Analizowałem aktywność w bazie danych. W pewnym momencie widziałem 35 oddzielnych wniosków zablokowanych w jednym punkcie procesu. Wszystkie te identyfikatory SPID miały czas oczekiwania rzędu 50 ms LATCH_EXna zasób METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8). Jeden SPID ma ten zasób, a wszystkie inne blokują. Nie znalazłem nic na temat tego zasobu oczekiwania podczas wyszukiwania w sieci.

Tabela w tempdb, której używamy, ma IDENTITY(1,1) kolumnę. Czy te identyfikatory SPID czekają na kolumnę TOŻSAMOŚĆ? Jakie metody moglibyśmy zastosować w celu zmniejszenia lub wyeliminowania blokowania?

Serwer jest częścią klastra. Na serwerze działa 64-bitowy program SQL Server 2012 Standard Edition SP1 w 64-bitowym systemie Windows 2008 R2 Enterprise. Serwer ma 64 GB pamięci RAM i 48 procesorów, ale baza danych może używać tylko 16, ponieważ jest to edycja standardowa.

(Pamiętaj, że nie jestem podekscytowany projektem użycia stałej tabeli w tempdb do przechowywania wszystkich tych danych. Zmiana tego byłaby interesującym wyzwaniem technicznym i politycznym, ale jestem otwarta na sugestie).

AKTUALIZACJA 23.03.2013

Otworzyliśmy skrzynkę pomocy technicznej w firmie Microsoft. Będę aktualizować to pytanie, gdy będziemy dowiedzieć się więcej.

AKTUALIZACJA 5/10/2013

Inżynier wsparcia SQL Server zgodził się, że oczekiwania zostały spowodowane przez kolumnę TOŻSAMOŚĆ. Usunięcie TOŻSAMOŚCI wyeliminowało oczekiwania. Nie mogliśmy powielić problemu na SQL 2008 R2; miało to miejsce tylko w SQL 2012.


Czy proces zasadniczo kopiuje dane z tabel #Temporary do tabeli stałej, czy też na tym etapie dzieje się dodatkowa logika transformacji?
Jon Seigel,

Na etapie, na który czeka, kopiuje rekordy zapasów jednego sklepu do stałej tabeli bez transformacji. Przez cały czas moglibyśmy pracować wewnątrz stałego stołu, ale myślę, że programista zdecydował się użyć stołu #Temporary jako obszaru przechowywania, aby zapobiec częstej aktualizacji danych przed przekształceniem w blokady PAGE.
Paul Williams,

Odpowiedzi:


4

Zakładając, że możesz wyizolować problem z generowaniem wartości tożsamości (spróbuj usunąć tę kolumnę jako test), zaleciłbym to:

  1. Usuń IDENTITYwłaściwość z kolumny w końcowej tabeli.
  2. Wygeneruj wartości tożsamości w każdej z tabel #Temporary.
  3. Podczas ładowania końcowej tabeli połącz identyfikator numeryczny dla konkretnego sklepu z wartościami tożsamości z kroku 2.

Więc jeśli masz identyfikatory sklepu 3 i 4, uzyskasz końcowe wartości identyfikatora takie jak to:

3000000001
3000000002
3000000003
...
4000000001
4000000002
...

Lub coś podobnego do tego. Masz pomysł.

Wyeliminuje to potrzebę serializacji przy IDENTITYgenerowaniu, jednocześnie zachowując wyjątkowość w końcowym wyniku.

Alternatywnie, w zależności od tego, jak działa proces, wstaw końcowe obliczone wartości id do tabel #Temporary. Następnie możesz utworzyć widok, który UNION ALLjest nimi razem, eliminując w ogóle potrzebę kopiowania danych.


Dziękuję za odpowiedź. Zgadzam się, jeśli to jest problem, użycie jakiegoś wyprodukowanego klucza (lub żadnego klucza) może to naprawić. Otworzyliśmy sprawę z Microsoft dotyczącą tego problemu. Opublikuję wynik tutaj i zaakceptuję twoją odpowiedź, jeśli zgodzą się, że to jest problem.
Paul Williams,

@Paul: Daj mi znać; Jestem równie ciekawa. Podobnie jak ty, nie byłem w stanie znaleźć niczego w Internecie na temat tej zatrzasku, ale z pewnością rozsądne jest, że jest to serializacja tożsamości / sekwencji. Trudno powiedzieć, czy to jest wąskie gardło, choć wydaje się prawdopodobne, że ponad 30 wątków konkuruje o wartości. Możesz także spróbować skopiować z każdej tabeli #Temporary szeregowo (zamiast równolegle), aby sprawdzić, czy to pomoże.
Jon Seigel

2
Inżynier SQL Server zgodził się, że to prawdopodobnie IDENTITYkolumna. Usunęliśmy go z już szerokiego indeksu klastrowego i całkowicie usunęliśmy kolumnę. To nie było konieczne. Następnie te LATCH_EX oczekiwania zniknęły. Nie mogliśmy powielić oczekiwań na SQL 2008 R2. Problem pojawił się tylko na SQL Server 2012.
Paul Williams

@Paul: Dziękujemy za informację. Bardzo interesujące. Zgaduję, że kod, który generuje IDENTITYwartości, został przepisany w celu użycia nowej funkcji generowania sekwencji, która była nowa w 2012 roku. W <2012 roku możesz zobaczyć inny typ zatrzasku, chociaż jeśli nie było problemu z perf, to wydaje się, że był regresja w kodzie. W każdym razie usunięcie IDENTITYkolumny jest najbezpieczniejsze.
Jon Seigel

Zamiast tożsamości możesz spróbować użyć „SEKWENCJI” (która jest nowa w SQL 2012)
Bogdan Maxim

7

(Zaktualizowano w lutym 2019 r.)

To jest stary post, który powiedział, że w końcu udało mi się przekonać Microsoft, że sam fakt, który to się dzieje, jest rzeczywiście wadą.

Aktualizacja: MS potwierdziło błąd i przypisało mu błąd nr 12628722.

Widziałem ten post w listopadzie 2018 r., Kiedy zaczęliśmy odczuwać podobne skutki po aktualizacji z Sql Server 2005 do Sql Server 2017. Tabela o wielkości 3,3 miliona wierszy, która zwykła zajmować 10 sekund, zaczęła nagle przyjmować 10 minuty na tabelach z Identitykolumnami.

Okazuje się, że kryją się za tym dwa problemy:

  1. Firma Microsoft zmieniła zachowanie w Sql Server 2014, aby wymusić uruchamianie wkładek luzem w trybie równoległym - we wcześniejszych wersjach wkładki luzem miały plan szeregowy.
  2. Po uruchomieniu równolegle na naszym 32-rdzeniowym pudełku silnik spędził więcej czasu, blokując się rdzeniami, niż wykonując pracę.

Zajęło mi to 4 tygodnie, ale zaraz po wakacjach dostałem spóźniony prezent od Świętego Mikołaja - potwierdzenie, że problem był rzeczywiście wadą.

Znaleźliśmy kilka możliwych obejść, dopóki nie zostanie to naprawione:

  1. Użyj Option (MaxDop 1)w zapytaniu, aby przekształcić wstawkę zbiorczą z powrotem w plan szeregowy.
  2. Zamaskuj kolumnę Tożsamość, przesyłając ją (np. Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn)
    • zapobiega to kopiowaniu właściwości tożsamości podczas używania SELECT...INTO
  3. Usuń kolumnę tożsamości, jak opisano powyżej.
  4. Zmień tryb zgodności bazy danych na Sql Server 2012 lub niższy, aby ponownie ustanowić plan serializowany.

Aktualizacja: Poprawka, którą MS wdroży, polega na przywróceniu tego rodzaju wkładek z powrotem do korzystania z Serialized planu. Jest to planowane dla Sql Server 2017 CU14 (brak wiadomości o innych wersjach Sql Server - przepraszam!). Po wdrożeniu flaga śledzenia 9492 będzie musiała zostać włączona na poziomie serwera lub za pośrednictwem DBCC TraceOn .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.