Sprawdzanie zmian w tabeli SQL Server?

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

Chciałbym móc obsługiwać dowolny SQL Server 2000 SP4 lub nowszy. Moja aplikacja to wizualizacja danych dla produktu innej firmy. Nasza baza klientów jest w tysiącach, więc nie chcę stawiać wymagań, aby zmodyfikować stronę trzecią stół sprzedawcy przy każdej instalacji.

Przez "zmiany w tabeli" mam na myśli zmiany danych tabeli, a nie zmiany struktury tabeli.

Ostatecznie chciałbym, aby zmiana wywołała Zdarzenie w mojej aplikacji, zamiast sprawdzać zmiany w interwale.


Najlepszym sposobem działania biorąc pod uwagę moje wymagania (brak wyzwalaczy lub modyfikacji schematu, SQL Server 2000 i 2005) wydaje się użycie funkcji BINARY_CHECKSUM w T-SQL. Sposób, w jaki planuję implementacja jest następująca:

Co X sekund uruchom następujące zapytanie:

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

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

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

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

Author: Nhan, 2008-08-01

8 answers

Spójrz na polecenie sumy kontrolnej:

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

Zwróci ten sam numer za każdym razem, gdy zostanie uruchomiony, 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 odbudowy zależności bufora po zmianie tabel:
ASP.NET 1.1 zależność bufora bazy danych (bez wyzwalaczy)

 93
Author: Jon Galloway,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-28 03:44:42

niestety suma kontrolna nie zawsze działa poprawnie, aby wykryć zmiany. Jest to tylko prymitywna suma kontrolna i brak obliczeń CRC. Dlatego nie można go użyć do wykrycia wszystkich zmian, np. zmiany symetryczne powodują tę samą sumę kontrolną!

Np. rozwiązanie z CHECKSUM_AGG(BINARY_CHECKSUM(*)) dostarcza zawsze 0 dla wszystkich 3 tabel o różnej treś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!

 30
Author: BitLauncher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-29 02:34:15

Dlaczego nie chcesz użyć wyzwalaczy? Są dobrą rzeczą, jeśli używasz ich poprawnie. Jeśli używasz ich jako sposobu na wyegzekwowanie integralności odniesienia, to wtedy przechodzą z dobrego na złe. Ale jeśli używasz ich do monitorowania, nie są one tak naprawdę uważane za tabu.

 26
Author: Nick Berardi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-26 17:38:44

Jak często trzeba sprawdzać zmiany i jak duże (pod względem wielkości wiersza) są tabele w bazie danych? Jeśli użyjesz metody CHECKSUM_AGG(BINARY_CHECKSUM(*)) zasugerowanej przez Johna, skanuje ona każdy wiersz podanej tabeli. Podpowiedź NOLOCK pomaga, ale w dużej bazie danych wciąż trafiasz w każdy wiersz. Będziesz również musiał przechowywać sumę kontrolną dla każdego wiersza, aby powiedzieć, że jeden się zmienił.

Czy rozważałeś pójście na to z innej strony? Jeśli nie chcesz modyfikować schematu do dodaj wyzwalacze (co ma sens, to nie twoja baza danych), czy rozważałeś współpracę z dostawcą aplikacji, który tworzy bazę danych?

Mogliby zaimplementować API, które zapewnia mechanizm powiadamiania aplikacji akcesoriów o zmianie danych. Może to być tak proste, jak zapisanie do tabeli powiadomień, która wyświetla tabelę i który wiersz został zmodyfikowany. Można to zaimplementować za pomocą wyzwalaczy lub kodu aplikacji. Z twojej strony, ti nie ma znaczenia, twoja jedyna troska będzie okresowo skanować tabelę 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że to być obsługiwane w całości przez SQL za pomocą wyzwalaczy, możesz wykonać dla nich większość pracy, pisząc i testując wyzwalacze, a następnie dostarczając kod do dostawcy aplikacji. Mając dostawcę obsługi wyzwalaczy, zapobiega sytuacja, w której dodanie wyzwalacza przypadkowo zastępuje WYZWALACZ dostarczony przez dostawcę.

 20
Author: Chris Miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-14 12:19:25

Ma zadanie DTS (lub zadanie uruchamiane przez usługę windows), które działa w danym przedziale czasowym. Przy każdym uruchomieniu pobiera informacje o podanej tabeli za pomocą tabel system INFORMATION_SCHEMA i zapisuje te dane w repozytorium danych. Porównuje zwrócone dane dotyczące struktury tabeli z danymi zwróconymi w poprzednim czasie. Jeśli jest inaczej, to wiesz, że struktura się zmieniła.

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

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

Będziesz monitorować różne kolumny i widoki INFORMATION_SCHEMA w zależności od tego, jak dokładnie zdefiniujesz "zmiany w tabeli".

 18
Author: Yaakov Ellis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-01 14:06:28

Niestety, nie sądzę, aby w SQL2000 można było to zrobić w czysty sposób. Jeśli zawęzisz swoje wymagania do SQL Server 2005 (i nowszych), to jesteś w biznesie. Możesz użyć klasy SQLDependency w System.Data.SqlClient. Zobacz powiadomienia o zapytaniach w SQL Server (ADO.NET).

 18
Author: caryden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 20:42:28

Zgaduj tutaj: jeśli nie chcesz modyfikować tabel stron trzecich, czy możesz utworzyć widok, a następnie uruchomić ten widok?

 13
Author: Orion Edwards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-05 01:12:37

Sprawdź ostatnią datę zatwierdzenia. Każda baza danych ma historię, kiedy każdy commit jest tworzony. Uważam, że to Norma zgodności z kwasem.

 7
Author: ECE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 04:58:25