Sprawdź zmiany w tabeli programu SQL Server?

142

Jak mogę monitorować bazę danych SQL Server pod kątem zmian w tabeli bez używania wyzwalaczy lub modyfikowania w jakikolwiek sposób struktury bazy danych? Moje preferowane środowisko programistyczne to .NET i C #.

Chciałbym móc obsługiwać dowolny SQL Server 2000 SP4 lub nowszy. Moja aplikacja to skręcana wizualizacja danych dla produktu innej firmy. Nasza baza klientów jest w tysiącach, więc nie chcę nakładać wymagań, aby modyfikować tabelę zewnętrznego dostawcy przy każdej instalacji.

Przez „zmiany w tabeli” rozumiem zmiany danych tabeli, a nie zmiany struktury tabeli.

Ostatecznie chciałbym, aby zmiana wyzwalała zdarzenie w mojej aplikacji, zamiast sprawdzać zmiany w odstępach czasu.


Wydaje się, że najlepszym sposobem działania, biorąc pod uwagę moje wymagania (brak wyzwalaczy lub modyfikacji schematu, SQL Server 2000 i 2005), jest użycie BINARY_CHECKSUMfunkcji w T-SQL . Sposób, w jaki planuję wdrożyć, jest następujący:

Co X sekund uruchamiaj następujące zapytanie:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

I porównaj to z wartością przechowywaną. Jeśli wartość uległa zmianie, przejdź przez tabelę wiersz po wierszu, używając zapytania:

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

I porównaj zwrócone sumy kontrolne z zapisanymi wartościami.

TimM
źródło
3
Nie zdarzyło im się umieścić w swoich wierszach ostatnio zmodyfikowanej sygnatury czasowej, prawda?
zmbq
Dla przypomnienia, jeśli obsługiwana wersja to SQL Server 2005 lub nowsza. Przyjrzę się funkcji Service Broker w SQL Server.
Marco Guignard

Odpowiedzi:

97

Spójrz na polecenie SUMA KONTROLNA:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);

To zwróci tę samą liczbę za każdym razem, gdy zostanie uruchomiona, o ile zawartość tabeli nie ulegnie zmianie. Zobacz mój post na ten temat, aby uzyskać więcej informacji:

SUMA KONTROLNA

Oto jak go użyłem do odbudowania zależności pamięci podręcznej po zmianie tabel:
Zależność pamięci podręcznej bazy danych ASP.NET 1.1 (bez wyzwalaczy)

Jon Galloway
źródło
2
Sumy kontrolne mogą i ostatecznie zawiodą. Jeśli twój system akceptuje, że dwa różne zestawy danych dadzą tę samą sumę kontrolną, nic ci nie jest. Z tego powodu musiałem odejść od sum kontrolnych w większości naszych systemów ...
LPains
@LPains Czy możesz rozwinąć swoje oświadczenie?
petrosmm,
1
@petrosmm Nie jestem pewien, co konkretnie mam rozwinąć, ale spróbuję. Wyobraź sobie, że masz tabelę z kilkuset rekordami, generujesz w zasadzie liczbę całkowitą jako sumę kontrolną, jak często to się zderzy? W moim przypadku robiłem to z około 10 tabelami, wszystkie z setkami rekordów. Miałem co najmniej jedną kolizję dziennie. Sprawdź inną odpowiedź stackoverflow.com/questions/14450415/ ...
LPains
29

Niestety SUMA KONTROLNA nie zawsze działa poprawnie w celu wykrycia zmian .

Jest to tylko prymitywna suma kontrolna i brak obliczeń cyklicznej kontroli nadmiarowej (CRC).

Dlatego nie można go używać do wykrywania wszystkich zmian, np. Zmiany symetryczne skutkują tą samą SUMĄ KONTROLNĄ!

E. g. rozwiązanie z CHECKSUM_AGG(BINARY_CHECKSUM(*))zawsze zapewni 0 dla wszystkich 3 tabel o różnej zawartości:


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 1 as numA, 2 as numB UNION ALL SELECT 1 as numA, 2 as numB ) q -- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 0 as numA, 0 as numB UNION ALL SELECT 0 as numA, 0 as numB ) q -- delivers 0!

BitLauncher
źródło
5
To właściwie nie jest odpowiedź, to „Twoja sugestia nie działa”.
kristianp
1
Można temu zaradzić w przypadku zduplikowanych danych, używając słowa kluczowego DISINCT przed BINARY_CHECKSUM. Omówiono tutaj kilka innych pułapek , ale nie są to dokładnie typowe scenariusze.
pblack
25

Dlaczego nie chcesz używać wyzwalaczy? Są dobrą rzeczą, jeśli używasz ich poprawnie. Jeśli używasz ich jako sposobu na wymuszenie integralności referencyjnej, wtedy zmieniają się z dobrych w złe. Ale jeśli używasz ich do monitorowania, nie są tak naprawdę uważane za tabu.

Nick Berardi
źródło
20

Jak często musisz sprawdzać zmiany i jak duże (pod względem wielkości wierszy) są tabele w bazie danych? Jeśli użyjesz CHECKSUM_AGG(BINARY_CHECKSUM(*))metody sugerowanej przez Johna, przeskanuje każdy wiersz określonej tabeli. NOLOCKWskazówka pomoże, ale na dużej bazie danych, nadal uderzania każdy wiersz. Będziesz także musiał zapisać sumę kontrolną dla każdego wiersza, aby powiedzieć, że jeden się zmienił.

Czy zastanawiałeś się nad tym z innej perspektywy? Jeśli nie chcesz modyfikować schematu w celu dodania wyzwalaczy (co ma sens, to nie twoja baza danych), czy rozważałeś współpracę z dostawcą aplikacji, który tworzy bazę danych?

Mogliby zaimplementować interfejs API zapewniający mechanizm powiadamiania dodatkowych aplikacji o zmianie danych. Może to być tak proste, jak zapisanie do tabeli powiadomień, która zawiera listę tabeli i wiersza, który został zmodyfikowany. Można to zaimplementować za pomocą wyzwalaczy lub kodu aplikacji. Z Twojej strony nie ma to znaczenia, jedynym zmartwieniem byłoby okresowe skanowanie tabeli powiadomień. Wydajność bazy danych byłaby znacznie mniejsza niż skanowanie każdego wiersza w poszukiwaniu zmian.

Najtrudniejsze byłoby przekonanie dostawcy aplikacji do wdrożenia tej funkcji. Ponieważ można to obsługiwać całkowicie za pomocą języka SQL za pośrednictwem wyzwalaczy, większość pracy można wykonać, pisząc i testując wyzwalacze, a następnie przekazując kod do dostawcy aplikacji. Jeśli dostawca obsługuje wyzwalacze, zapobiega to sytuacji, w której dodanie wyzwalacza nieumyślnie zastępuje wyzwalacz dostarczony przez dostawcę.

Chris Miller
źródło
16

Mieć zadanie DTS (lub zadanie uruchamiane przez usługę systemu Windows) działające w określonych odstępach czasu. Za każdym razem, gdy jest uruchamiany, pobiera informacje o danej tabeli przy użyciu systemowych tabel INFORMATION_SCHEMA i zapisuje te dane w repozytorium danych. Porównaj zwrócone dane dotyczące struktury tabeli z danymi zwróconymi poprzednim razem. Jeśli jest inny, wiesz, że struktura uległa zmianie.

Przykładowe zapytanie zwracające informacje dotyczące wszystkich kolumn w tabeli ABC (najlepiej wyszczególniając tylko kolumny z tabeli INFORMATION_SCHEMA, które chcesz, zamiast używać * select **, tak jak tutaj):

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

Należy monitorować różne kolumny i widoki INFORMACJE_SCHEMA w zależności od tego, jak dokładnie zdefiniujesz „zmiany w tabeli”.

Yaakov Ellis
źródło
2
Pytanie dotyczy zmian w danych tabeli, a information_schema zawiera schemat (definicje kolumn) tabeli.
też
13

Zgadnij tutaj: jeśli nie chcesz modyfikować tabel strony trzeciej, czy możesz utworzyć widok, a następnie ustawić wyzwalacz w tym widoku?

Orion Edwards
źródło
6

Sprawdź datę ostatniego zatwierdzenia. W każdej bazie danych znajduje się historia każdego zatwierdzenia. Uważam, że jest to standard zgodności z ACID.

ECE
źródło
1
Proszę przedstawić udokumentowany sposób uzyskania zakresu tych informacji w tabeli w programie SQL Server
Martin Smith