Wie kann ich eine SQL Server-Datenbank auf Änderungen an einer Tabelle überwachen, ohne Trigger zu verwenden oder die Struktur der Datenbank in irgendeiner Weise zu ändern? Meine bevorzugte Programmierumgebung ist .NET und C #.
Ich möchte in der Lage sein, SQL Server 2000 SP4 oder neuer zu unterstützen. Meine Anwendung ist eine integrierte Datenvisualisierung für das Produkt eines anderen Unternehmens. Unser Kundenstamm liegt bei Tausenden, daher möchte ich nicht bei jeder Installation die Anforderungen stellen müssen, dass wir die Tabelle des Drittanbieters ändern.
Mit "Änderungen an einer Tabelle" meine ich Änderungen an Tabellendaten, nicht Änderungen an der Tabellenstruktur.
Letztendlich möchte ich, dass die Änderung ein Ereignis in meiner Anwendung auslöst, anstatt in regelmäßigen Abständen nach Änderungen suchen zu müssen.
Die beste Vorgehensweise angesichts meiner Anforderungen (keine Trigger oder Schemaänderungen, SQL Server 2000 und 2005) scheint darin zu bestehen, die BINARY_CHECKSUM
Funktion in T-SQL zu verwenden . Die Art und Weise, wie ich sie implementieren möchte, ist folgende:
Führen Sie alle X Sekunden die folgende Abfrage aus:
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);
Und vergleichen Sie das mit dem gespeicherten Wert. Wenn sich der Wert geändert hat, gehen Sie die Tabelle Zeile für Zeile mit der folgenden Abfrage durch:
SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);
Und vergleichen Sie die zurückgegebenen Prüfsummen mit gespeicherten Werten.
quelle
Antworten:
Schauen Sie sich den Befehl CHECKSUM an:
Dies gibt bei jeder Ausführung dieselbe Nummer zurück, solange sich der Tabelleninhalt nicht geändert hat. Weitere Informationen finden Sie in meinem Beitrag dazu:
CHECKSUM
So habe ich es verwendet, um Cache-Abhängigkeiten wiederherzustellen, wenn sich Tabellen geändert haben:
ASP.NET 1.1-Datenbank-Cache-Abhängigkeit (ohne Trigger)
quelle
Leider funktioniert CHECKSUM nicht immer richtig, um Änderungen zu erkennen .
Es handelt sich nur um eine primitive Prüfsumme und keine CRC-Berechnung (Cyclic Redundancy Check).
Daher können Sie damit nicht alle Änderungen erkennen, z. B. führen symmetrische Änderungen zu derselben CHECKSUM!
Z.B. Die Lösung mit
CHECKSUM_AGG(BINARY_CHECKSUM(*))
liefert immer 0 für alle 3 Tabellen mit unterschiedlichem Inhalt:quelle
Warum möchten Sie keine Trigger verwenden? Sie sind eine gute Sache, wenn Sie sie richtig verwenden. Wenn Sie sie als Mittel zur Durchsetzung der referenziellen Integrität verwenden, wechseln sie von gut zu schlecht. Wenn Sie sie jedoch zur Überwachung verwenden, gelten sie nicht wirklich als Tabu.
quelle
Wie oft müssen Sie nach Änderungen suchen und wie groß (in Bezug auf die Zeilengröße) sind die Tabellen in der Datenbank? Wenn Sie die
CHECKSUM_AGG(BINARY_CHECKSUM(*))
von John vorgeschlagene Methode verwenden, wird jede Zeile der angegebenen Tabelle gescannt. DerNOLOCK
Hinweis hilft, aber in einer großen Datenbank treffen Sie immer noch jede Zeile. Sie müssen auch die Prüfsumme für jede Zeile speichern, damit Sie feststellen können, dass sich eine geändert hat.Haben Sie darüber nachgedacht, dies aus einem anderen Blickwinkel zu betrachten? Wenn Sie das Schema nicht ändern möchten, um Trigger hinzuzufügen (was sinnvoll ist, es ist nicht Ihre Datenbank), haben Sie darüber nachgedacht, mit dem Anwendungsanbieter zusammenzuarbeiten, der die Datenbank erstellt?
Sie könnten eine API implementieren, die einen Mechanismus zum Benachrichtigen von Zubehör-Apps bereitstellt, wenn sich Daten geändert haben. Es könnte so einfach sein, in eine Benachrichtigungstabelle zu schreiben, in der aufgeführt ist, welche Tabelle und welche Zeile geändert wurden. Dies könnte durch Trigger oder Anwendungscode implementiert werden. Von Ihrer Seite aus wäre das egal, Ihr einziges Anliegen wäre es, die Benachrichtigungstabelle regelmäßig zu scannen. Der Leistungseinbruch in der Datenbank wäre weitaus geringer als das Scannen jeder Zeile nach Änderungen.
Der schwierige Teil wäre, den Anwendungsanbieter davon zu überzeugen, diese Funktion zu implementieren. Da dies vollständig über SQL über Trigger erledigt werden kann, können Sie den Großteil der Arbeit für sie erledigen, indem Sie die Trigger schreiben und testen und dann den Code zum Anwendungsanbieter bringen. Indem der Anbieter die Trigger unterstützt, wird verhindert, dass das Hinzufügen eines Triggers versehentlich einen vom Anbieter bereitgestellten Trigger ersetzt.
quelle
Leider glaube ich nicht, dass es in SQL2000 einen sauberen Weg gibt, dies zu tun. Wenn Sie Ihre Anforderungen auf SQL Server 2005 (und höher) beschränken, sind Sie im Geschäft. Sie können die
SQLDependency
Klasse in verwendenSystem.Data.SqlClient
. Siehe Abfragebenachrichtigungen in SQL Server (ADO.NET) .quelle
Haben Sie einen DTS-Job (oder einen Job, der von einem Windows-Dienst gestartet wird), der in einem bestimmten Intervall ausgeführt wird. Bei jeder Ausführung werden mithilfe der Systemtabellen INFORMATION_SCHEMA Informationen zur angegebenen Tabelle abgerufen und diese Daten im Datenrepository aufgezeichnet. Vergleichen Sie die Daten, die bezüglich der Struktur der Tabelle zurückgegeben wurden, mit den Daten, die beim vorherigen Mal zurückgegeben wurden. Wenn es anders ist, wissen Sie, dass sich die Struktur geändert hat.
Beispielabfrage zur Rückgabe von Informationen zu allen Spalten in Tabelle ABC (im Idealfall werden nur die Spalten aus der Tabelle INFORMATION_SCHEMA aufgelistet, die Sie möchten, anstatt wie hier * select ** zu verwenden):
Sie würden verschiedene Spalten und INFORMATION_SCHEMA-Ansichten überwachen, je nachdem, wie genau Sie "Änderungen an einer Tabelle" definieren.
quelle
Wilde Vermutung hier: Wenn Sie die Tabellen von Drittanbietern nicht ändern möchten, können Sie eine Ansicht erstellen und dann einen Auslöser für diese Ansicht setzen?
quelle
Überprüfen Sie das letzte Festschreibungsdatum. Jede Datenbank hat einen Verlauf, wann jedes Commit durchgeführt wird. Ich glaube, es ist ein Standard für die Einhaltung von Säuren.
quelle