Frage

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 .NETZ und C#.

Ich möchte jeden unterstützen können SQL Server 2000 SP4 oder neuer.Meine Anwendung ist eine ergänzende Datenvisualisierung für das Produkt eines anderen Unternehmens.Unser Kundenstamm geht in die Tausende, daher möchte ich nicht verlangen, dass wir bei jeder Installation die Tabelle des Drittanbieters ändern.

Von „Änderungen an einer Tabelle“ Ich meine Ä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.


Angesichts meiner Anforderungen (keine Trigger oder Schemaänderungen, SQL Server 2000 und 2005) scheint die beste Vorgehensweise die Verwendung von zu sein BINARY_CHECKSUM Funktion in T-SQL.Die Art und Weise, wie ich es umsetzen 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 Abfrage durch:

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

Und vergleichen Sie die zurückgegebenen Prüfsummen mit gespeicherten Werten.

War es hilfreich?

Lösung

Schauen Sie sich den CHECKSUM-Befehl an:

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

Dadurch wird bei jeder Ausführung dieselbe Zahl zurückgegeben, solange sich der Tabelleninhalt nicht geändert hat.Weitere Informationen finden Sie in meinem Beitrag dazu:

PRÜFSUMME

So habe ich es verwendet, um Cache-Abhängigkeiten neu zu erstellen, wenn sich Tabellen geändert haben:
ASP.NET 1.1-Datenbank-Cache-Abhängigkeit (ohne Trigger)

Andere Tipps

Leider funktioniert CHECKSUM nicht immer ordnungsgemäß, um Änderungen zu erkennen.

Es handelt sich lediglich um eine primitive Prüfsumme und keine CRC-Berechnung (Cyclic Redundancy Check).

Daher können Sie damit nicht alle Änderungen erkennen, z.G.Symmetrische Änderungen führen zur gleichen CHECKSUM!

E.G.die Lösung mit CHECKSUM_AGG(BINARY_CHECKSUM(*)) liefert immer 0 für alle 3 Tabellen mit unterschiedlichem Inhalt:


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!

Wählen Sie Checksum_agg (Binary_Checksum (*)) aus (wählen Sie 1 als NUMA, 2 als Numb Union alle auswählen 1 als NUMA, 2 als Numb) q - liefert 0!

Wählen Sie Checksum_agg (Binary_Checksum (*)) aus (SELECT 0 AS NUMA, 0 AS Numb Union alle wählen 0 als Numa, 0 als Numb) Q - Ligert 0!

Warum möchten Sie keine Trigger verwenden?Sie sind eine gute Sache, wenn man sie richtig anwendet.Wenn Sie sie nutzen, um die referenzielle Integrität durchzusetzen, dann werden sie vom Guten zum Schlechten.Aber wenn man sie zur Überwachung nutzt, gelten sie nicht wirklich als Tabu.

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 verwenden CHECKSUM_AGG(BINARY_CHECKSUM(*)) Mit der von John vorgeschlagenen Methode wird jede Zeile der angegebenen Tabelle gescannt.Der NOLOCK hint hilft, aber in einer großen Datenbank treffen Sie immer noch jede Zeile.Sie müssen außerdem die Prüfsumme für jede Zeile speichern, damit Sie erkennen, dass sich eine Zeile 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 Sinn macht, da es sich nicht um Ihre Datenbank handelt), haben Sie darüber nachgedacht, mit dem Anwendungsanbieter zusammenzuarbeiten, der die Datenbank erstellt?

Sie könnten eine API implementieren, die einen Mechanismus zur Benachrichtigung von Zusatz-Apps über Datenänderungen bietet.Es könnte so einfach sein, in eine Benachrichtigungstabelle zu schreiben, die auflistet, welche Tabelle und welche Zeile geändert wurden.Dies könnte durch Trigger oder Anwendungscode implementiert werden.Für Sie wäre das egal, Ihre einzige Sorge wäre, die Benachrichtigungstabelle regelmäßig zu scannen.Die Leistungseinbußen in der Datenbank wären weitaus geringer, als wenn jede Zeile nach Änderungen durchsucht würde.

Der schwierige Teil wäre, den Anwendungsanbieter davon zu überzeugen, diese Funktion zu implementieren.Da dies vollständig über SQL über Trigger abgewickelt werden kann, könnten Sie den Großteil der Arbeit für sie erledigen, indem Sie die Trigger schreiben und testen und dann den Code zum Anwendungsanbieter bringen.Dadurch, dass der Anbieter die Trigger unterstützt, wird verhindert, dass das Hinzufügen eines Triggers versehentlich einen vom Anbieter bereitgestellten Trigger ersetzt.

Leider glaube ich nicht, dass es in SQL2000 eine saubere Möglichkeit gibt, dies zu tun.Wenn Sie Ihre Anforderungen auf SQL Server 2005 (und höher) beschränken, sind Sie im Geschäft.Du kannst den ... benutzen SQLDependency Klasse in System.Data.SqlClient.Sehen Abfragebenachrichtigungen in SQL Server (ADO.NET).

Verfügen Sie über 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 des Systems Informationen über die angegebene Tabelle abgerufen INFORMATION_SCHEMA Tabellen und zeichnet diese Daten im Datenrepository auf.Vergleichen Sie die zurückgegebenen Daten bezüglich der Struktur der Tabelle mit den zuvor zurückgegebenen Daten.Wenn es anders ist, dann wissen Sie, dass sich die Struktur geändert hat.

Beispielabfrage zur Rückgabe von Informationen zu allen Spalten in Tabelle ABC (idealerweise werden nur die gewünschten Spalten aus der Tabelle INFORMATION_SCHEMA aufgelistet, anstatt *select ** zu verwenden, wie ich es hier tue):

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

Sie würden verschiedene Spalten und INFORMATION_SCHEMA-Ansichten überwachen, je nachdem, wie genau Sie „Änderungen an einer Tabelle“ definieren.

Wilde Vermutung hier:Wenn Sie die Tabellen des Drittanbieters nicht ändern möchten, können Sie eine Ansicht erstellen und dann einen Trigger auf diese Ansicht setzen?

Überprüfen Sie das letzte Commit-Datum.Jede Datenbank verfügt über einen Verlauf darüber, wann jedes Commit durchgeführt wurde.Ich glaube, es ist ein Standard der ACID-Konformität.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top