2009-06-13 9 views
9

Piszę kod rejestrowania/audytu, który będzie działał w produkcji (nie tylko w przypadku zgłaszania błędów lub podczas opracowywania). Po przeczytaniu Coding Horror's experiences with dead-locking and logging zdecydowałem, że powinienem zasięgnąć porady. (Rozwiązanie "niezalogowania się" przez Jeffa nie zadziała, jest to prawnie obowiązkowa kontrola bezpieczeństwa)Porady dotyczące minimalizowania blokowania w tabeli tylko dołącz do MS SQL Server?

Czy istnieje odpowiedni poziom izolacji w celu zminimalizowania rywalizacji i zablokowania? Jakieś wskazówki dotyczące zapytań, które mogę dodać do instrukcji insert lub procedury przechowywanej?

Dbam głęboko o integralność transakcji dla wszystkiego oprócz tabeli kontroli. Chodzi o to, że tyle się zaloguje, że jeśli kilka wpisów nie powiedzie się, to nie jest problem. Jeśli rejestracja zatrzyma jakąś inną transakcję - to byłoby złe.

Mogę zalogować się do bazy danych lub pliku, chociaż logowanie do pliku jest mniej atrakcyjne, ponieważ muszę w jakiś sposób wyświetlić wyniki. Zalogowanie się do pliku może (prawie) zagwarantować, że rejestracja nie zakłóci działania innego kodu.

+0

jaka wersja serwera sql? –

+0

SQL 2000, chociaż istnieją pogłoski, że pewnego dnia biuro przejdzie do SQL 2008. – MatthewMartin

Odpowiedz

5

Normalna transakcja (np. READ COMMITTED) insert już wykonuje "minimalne" blokowanie. Wstawianie intensywnych aplikacji nie powoduje zakleszczeń na wkładce, niezależnie od kolejności mieszania wkładki z innymi operacjami. W najgorszym przypadku intensywny system wstawiania może powodować rywalizację zatrzasku strony w gorącym miejscu, w którym występuje wstawka, ale nie w przypadku zakleszczeń.

Aby spowodować zakleszczenia jak opisane przez Jeff nie musi być bardziej w grę, jak jednego z następujących powodów:

  • System korzysta wyższy poziom izolacji (mieli to nadchodzi wtedy, a także na to zasługują)
  • zostali odczyt z tabeli dziennika podczas transakcji (więc nie ma już „dołączyć tylko”)
  • łańcuch zakleszczenia zaangażowane zamki warstwa aplikacji (np. .Net lock oświadczenia w ramach log4net) powodując jest niewykrywalna zakleszczenia (tzn. zawiesza się aplikacja). Biorąc pod uwagę, że rozwiązanie problemu polega na analizie zrzutów procesowych, myślę, że jest to scenariusz, który mieli.

Tak długo, jak wstawiasz tylko logowanie w transakcjach na poziomie ODZYSKIWANIA ODZYSKANYCH, jesteś bezpieczny. Jeśli spodziewasz się tego samego problemu, podejrzewam, że SO miał (np. Zakleszczenia z blokadami aplikacji), to żadna ilość kreatora bazy danych nie może Cię uratować, ponieważ problem może się jeszcze pojawić, nawet jeśli logujesz się osobną transakcją lub w osobnym połączeniu.

+1

"Tak długo, jak wkładasz tylko logowanie w transakcjach na poziomie ODZYSKIWANIA ODZYSKIWANYCH, jesteś bezpieczny." To nie jest prawda. Jeśli uczestniczysz w dużej transakcji, możesz zablokować całą transakcję podczas próby wstawienia danych do tabeli rejestrowania (jeśli tabela rejestrowania jest zablokowana, ponieważ uruchamiasz jakiś zwariowany raport lub coś takiego). To także otwiera cię na środek impasu! –

+2

Nie, po prostu nieprawda. INSERT * nie * blokuje się za raportem (przeczytanym), niezależnie od tego, co robisz w transakcji. Równoczesne INSERTS nigdy nie pojawią się w łańcuchu impasu, ponieważ nie blokują się za sobą ani za SELECTs. Rzeczy, które mogą blokować wstawkę, to: blokada zasięgu S, która obejmuje punkt wstawienia (tj. Raport szeregowalny), blokadę S na stole (np. Eskalacja z raportu powtarzalnego) lub blokadę X (tj. Pewna aktywność * inna * niż "tylko dopisz", np. aktualizacje, które przeszły do ​​tabeli X lock). –

+2

WSTAWIĆ do tabeli (z indeksem klastrowym) w przeczytanym zobowiązaniu nabywa blokadę IX na stronie i X blokuje klucz. Jeśli nie może uzyskać IX blokady na stronie, będzie czekał, jeśli nie będzie mógł uzyskać, a X zablokuje klucz, to będzie czekać. Instrukcje SELECT wymagają wspólnych blokad. Zamki mogą być w konflikcie. Zakleszczenia mogą istnieć. Przeczytaj: http://msdn.microsoft.com/en-us/library/ms186396.aspx –

1

Ponieważ nie interesuje Cię integralność transakcyjna tabeli kontroli, można oczywiście wykonać rejestrowanie poza transakcją (tj. Po jej zakończeniu). To zminimalizuje wpływ na transakcję.

Ponadto, jeśli chcesz zminimalizować blokowanie, powinieneś postarać się, aby jak najwięcej obciążeń związanych z zapytaniem obejmowało indeksy nieklastrowe. (SQL Server 2005 i nowsze wersje, użycie instrukcji INCLUDE w indeksach NC może mieć duże znaczenie)

+0

Uwaga: jeśli wykonasz wszystkie operacje rejestrowania po zakończeniu transakcji, będzie to dość trudne do debugowania długich transakcji lub przerwanych transakcji. –

+0

Na plakacie już było jasne, że nie ma znaczenia, czy logowanie się nie powiedzie, o ile transakcja zostanie zakończona. Oczywiście transakcje powinny być tak krótkie, jak to tylko możliwe. –

+0

wszystko, co mówię, to to, że w tym kontekście (tj. W osobnym wątku) jest prawdopodobnie lepszy niż (tj. Po zakończeniu) –

1

Jednym ze sposobów na uniknięcie problemów z blokowaniem w przypadku "zwykłej" bazy danych jest niestosowanie tej samej bazy danych . Po prostu utwórz inną bazę danych do logowania. Jako bonus, szybki rozwój bazy danych logowania nie spowoduje fragmentacji w głównej bazie danych. Personall, zwykle wolę logować się do pliku - ale znowu jestem przyzwyczajony do robienia ciężkich manipulacji tekstem w moim edytorze - VIM. Logowanie się do oddzielnego DB powinno pomóc uniknąć problemów z zakleszczaniem.

Upewnij się tylko, że jeśli spróbujesz napisać swojego własnego programistę do bazy danych, z której korzystasz, będziesz bardzo ostrożny w kwestii swoich blokad (domyślam się, że to Jeff wpadł w blogu, do którego się odwołujesz). Prawidłowo napisane (zobacz kilka komentarzy w poście Jeffa), nie powinieneś mieć problemów z blokowaniem z twoją strukturą logowania, chyba że zrobi coś nieparzysta.

+0

Myślę, że wprowadzenie zupełnie nowej bazy danych tylko dla tabeli rejestrowania jest dość agresywne, zawsze możesz kontrolować lokalizację magazynu każdej tabeli przy użyciu grup plików, jeśli i tak jest to wymagane. Nie oznacza to również, że jeśli masz transakcję rozproszoną, logowanie do oddzielnej bazy danych może pogorszyć sytuację, jeśli ta operacja bierze udział w transakcji rozproszonej. –

+0

Jeśli korzystasz z transakcji rozproszonych, radzę * nie * mieć w nich wpisu do rejestru. Nie ma nic takiego, jak coś, co spowodowałoby przerwanie transakcji powodujące wycofanie transakcji, a nie posiadanie żadnych dzienników o tym, co się zepsuło ... –

5

Jeśli nie dbają o konsystencji na stole rejestrowania, dlaczego nie wykonywać wszystkie rejestrowanie z oddzielnym wątku.

Prawdopodobnie nie czekałbym na zakończenie transakcji przed rejestracją, ponieważ dziennik może odgrywać kluczową rolę w diagnozowaniu długich transakcji. Dzięki temu można zobaczyć całą pracę, którą wykonała wycofana transakcja.

Złap ślad stosu i wszystkie dane rejestrowania w wątku logowania, chuck it on a queue, gdy pojawiają się nowe komunikaty rejestrowania, wypróżnij je do bazy danych w pojedynczej transakcji.

Etapy ograniczenia do minimum blokowanie:

  • (Key) wykonywać wszystkie dodaje się do tabeli rejestrowania poza głównym gwintem/związku/transakcji.
  • Upewnij się, że tablica rejestrowania ma monotonnie rosnący indeks klastrowy (np. Tożsamość int), który zwiększa się za każdym razem, gdy dołączasz komunikat dziennika. Zapewnia to, że wstawiane strony są zwykle w pamięci i unika trafień wydajnościowych uzyskiwanych za pomocą tabel sterty.
  • Wykonaj wiele załączników do dziennika transakcji (10 wkładów w transakcji jest szybszych niż 10 wkładów poza transakcją i zwykle nabywają/zwalniają mniej blokad)
  • Daj sobie spokój. Rejestruj tylko do bazy danych co N milisekund. Uzupełnij bity prac.
  • Jeśli chcesz historycznie raportować rzeczy, możesz rozważyć podział swojej tabeli rejestrowania. Przykład: Możesz utworzyć nową tabelę rejestrowania co miesiąc, a jednocześnie mieć log VIEW, który jest UNION ALL ze wszystkich starszych tabel logowania. Wykonaj raportowanie w oparciu o najbardziej odpowiednie źródło.

Lepsza wydajność dzięki opróżnianiu wielu komunikatów rejestrowania w pojedynczej (mniejszej) transakcji i ma tę zaletę, że jeśli 10 wątków wykonuje pracę i loguje dane, tylko jeden wątek powoduje wypróżnianie zawartości do tabeli rejestrowania . To potokowanie rzeczywiście poprawia skalę.

Powiązane problemy