Discussion:
Referentielle Integrität abschalten
(zu alt für eine Antwort)
Rainer Budde
2005-07-12 11:10:25 UTC
Permalink
Hallo,

ich schreibe ein Programm das die Datenbestände von min. 2 SQL Servern
abgleichen soll. Die Tabellenstruktur ist auf beiden Servern identisch. Es
läuft im Prinzip folgendermaßen ab.

1. Hole alle Daten aus einer Tabelle aus SQL Server A
2. Vergleiche Daten der Tabelle aus SQL Server A mit der Tabelle aus SQL
Server B
a. Füge ggf. neue Datensätze der Tabelle auf SQL Server B hinzu
b. Lösche ggf. nicht mehr gebrauchte Datensätz der Tabelle auf SQL
Server B
c. Aktualisiere die Datensätze der Tabelle auf SQL Server B
3. Führe ein Update auf SQL Server B aus

Alle Schritte passieren in einem Rutsch und was viel wichtiger ist
Tabellenweise, d.h. ich knöpfe mir erst eine Tabelle vor und lasse alle
Schritte durchlaufen und dann die nächste Tabelle (die evtl. sogar von der
vorherigen abhängig ist). Genau das ist auch mein Problem! Da die Tabellen
sehr unterschiedlich untereinander verknüpft sind und auch noch eine
Referentielle Integrietät beinhalten kommt es zum Beispiel beim Löschen oder
Hinzufügen zu Fehlermeldungen.

Genau hier kann ich die Prüfung der RI nicht gebrauchen, da ich im nächsten
Schritt die abhänige Tabelle sowieso überarbeite und alle fehlenden Infos
eintragen werde (Natürlich mit Hilfe von Transaktionen über mehrere
Tabellen). Jetzt habe ich gelesen das ich mit Hilfe von ALTER TABLE WITH
NOCHECK die Referenzielle Integrität deaktivieren kann. Dazu habe ich noch
einige Fragen:

1. Hat jemand Erfahrung mit der Geschwindigkeit des "Alter Table WITH
NOCHECK" gemacht?

2. Wenn ich so vorgehe:
a) Start Transaktion
b) Alter Table WITH NOCHECK
c) Aktualisiere Daten auch über mehrere Tabellen
d) Alter Table WITH CHECK
e) Commit Transaktion

Ist das eine gute Variante und decken die Transaktionen auch das Alter TABLE
WITH NOCHECK ab?

3. Kann ich ALTER TABLE WITH NOCHECK ohne Probleme ausführen oder muss ich
exklusiven Zugriff erstellen?

4. Gibt es vielleicht eine bessere Variante (außer das hier und die RI
Rules)?

Danke Euch

Gruß Rainer
Elmar Boye
2005-07-13 07:32:50 UTC
Permalink
Hallo Rainer,
Post by Rainer Budde
ich schreibe ein Programm das die Datenbestände von min. 2 SQL Servern
abgleichen soll. Die Tabellenstruktur ist auf beiden Servern
identisch.
Wenns eine Kopie ist: Auch schon mal über Log Shipping nachgedacht?
Auch Replikation kann in einigen Szenarien schneller zu implementieren
sein.
Post by Rainer Budde
Es läuft im Prinzip folgendermaßen ab.
1. Hole alle Daten aus einer Tabelle aus SQL Server A
2. Vergleiche Daten der Tabelle aus SQL Server A mit der Tabelle aus
SQL Server B
a. Füge ggf. neue Datensätze der Tabelle auf SQL Server B hinzu
b. Lösche ggf. nicht mehr gebrauchte Datensätz der Tabelle auf SQL
Server B
c. Aktualisiere die Datensätze der Tabelle auf SQL Server B
3. Führe ein Update auf SQL Server B aus
Alle Schritte passieren in einem Rutsch und was viel wichtiger ist
Tabellenweise, d.h. ich knöpfe mir erst eine Tabelle vor und lasse
alle Schritte durchlaufen und dann die nächste Tabelle (die evtl.
sogar von der vorherigen abhängig ist). Genau das ist auch mein
Problem! Da die Tabellen sehr unterschiedlich untereinander verknüpft
sind und auch noch eine Referentielle Integrietät beinhalten kommt es
zum Beispiel beim Löschen oder Hinzufügen zu Fehlermeldungen.
Das sollte aber so hinzukriegen sein, dass es ohne Fehlermeldungen
geht. Denn auch wenn das etwas aufwändigere Aktualisierungsschritte
bedeutet.
Post by Rainer Budde
Genau hier kann ich die Prüfung der RI nicht gebrauchen, da ich im
nächsten Schritt die abhänige Tabelle sowieso überarbeite
Denn ansonsten "überrascht" Dich das Wiedereinschalten der
Einschränkungen am Schluss mit einer Fehlermeldung, weil irgendwo
Daten nicht gepasst haben. Und das Suchen ist kann wirklich
unerquicklich werden (wie ich bei Fremdimport von vermeintlich
sauberen Daten mehrfach erfahren habe).
Post by Rainer Budde
(Natürlich mit Hilfe von Transaktionen über mehrere Tabellen).
Die kannst Du dann auch weglassen ;-)
Post by Rainer Budde
1. Hat jemand Erfahrung mit der Geschwindigkeit des
"Alter Table WITH NOCHECK" gemacht?
Das geht quasi sofort, da NOCHECK bedeutet das nichts
geprüft wird.
Post by Rainer Budde
a) Start Transaktion
b) Alter Table WITH NOCHECK
Dir sollte klar sein das Abschalten global ist. Wenn also andere
parallel Daten einfügen, können sie das auch ohne referentielle
Prüfung tun.
Post by Rainer Budde
Ist das eine gute Variante und decken die Transaktionen auch das
Alter TABLE WITH NOCHECK ab?
Keine gute Variante: Durch Transaktion ist das zwar schon abgedeckt.
Nur müsstest Du schon eine "Monster"-Transaktion fahren, die über
alle Aktualisierungssschritte geht. Und "freust" Dich am Ende
über die Grösse des Protokolls wie über Dauer eines potentiellen
Rollbacks.
Post by Rainer Budde
3. Kann ich ALTER TABLE WITH NOCHECK ohne Probleme ausführen oder
muss ich exklusiven Zugriff erstellen?
Musst Du nicht. Für die betroffenen Tabellen ist allerdings eine
Schemaänderungssperre erforderlich. Was letztendlich bedeutet,
das keine andere Transaktionen aktiv sein dürfen, da Schemasperren
in der Hierarchie ganz oben stehen (keine anderen zulassen).
Post by Rainer Budde
4. Gibt es vielleicht eine bessere Variante (außer das hier
und die RI Rules)?
Stelle die Daten besser anfangs - ggf. in Arbeitstabellen - zusammen,
so dass sie sauber aktualisiert werden können. Und da es bei Dir
über mehrere Server geht, kann das auch unnötige verteilte
vermeiden, die beide Server belasten würden.
Für den Import würde ich eher DTS verwenden.

Gruss
Elmar
Rainer Budde
2005-07-13 10:28:38 UTC
Permalink
Hi,
Post by Elmar Boye
Wenns eine Kopie ist: Auch schon mal über Log Shipping nachgedacht?
Auch Replikation kann in einigen Szenarien schneller zu implementieren
sein.
es ist ein Abgleich mit einer gewissen Logik. Über Replikation hatten wir
auch schon mal nachgedacht aber sie ist dafür nicht intelligent genug.
Post by Elmar Boye
Die kannst Du dann auch weglassen ;-)
Lieber nicht ;)
Post by Elmar Boye
Das geht quasi sofort, da NOCHECK bedeutet das nichts
geprüft wird.
Jap, das habe ich auch schon festgestellt.
Post by Elmar Boye
Dir sollte klar sein das Abschalten global ist.
Global über die Tabelle, aber nicht über die DB!
Post by Elmar Boye
Wenn also andere
parallel Daten einfügen, können sie das auch ohne referentielle
Prüfung tun.
Aber nicht wenn ich es über eine Transaktion laufen lassen, d.h.

1. Transaktion starten
2. RI abschalten
3. Daten abgleichen
4. RI anschalten
5. Commit ausführen
Post by Elmar Boye
Keine gute Variante: Durch Transaktion ist das zwar schon abgedeckt.
Nur müsstest Du schon eine "Monster"-Transaktion fahren, die über
alle Aktualisierungssschritte geht. Und "freust" Dich am Ende
über die Grösse des Protokolls wie über Dauer eines potentiellen
Rollbacks.
Das stimmt, die Transaktion ist schon sehr groß. Allerdings sind es pro
aktualisierung nicht mehr als 400-500 Datensätze, so das ich damit leben
kann
Post by Elmar Boye
Musst Du nicht. Für die betroffenen Tabellen ist allerdings eine
Schemaänderungssperre erforderlich. Was letztendlich bedeutet,
das keine andere Transaktionen aktiv sein dürfen, da Schemasperren
in der Hierarchie ganz oben stehen (keine anderen zulassen).
Gut zu wissen!

Ich danke dir für eine Antworten.

Gruß Rainer
Elmar Boye
2005-07-14 07:59:35 UTC
Permalink
Hallo Rainer,
Post by Rainer Budde
Post by Elmar Boye
Dir sollte klar sein das Abschalten global ist.
Global über die Tabelle, aber nicht über die DB!
Ja. Das "global" war im Sinne aller Sitzungen die
auf die Tabelle zugreifen...
Post by Rainer Budde
Post by Elmar Boye
Wenn also andere
parallel Daten einfügen, können sie das auch ohne referentielle
Prüfung tun.
Aber nicht wenn ich es über eine Transaktion laufen lassen, d.h.
das ist Effekt der bereits angesprochenen Schema-Sperre, die
logischerweise während der gesamten Transaktion besteht.
Was allerdings ebenso bewirkt, dass während der Aktion niemand
sonst die Tabelle aktualisieren kann, du also alle parallel
zugreifenden Benutzer bblockieren kannst.

Gruss
Elmar

Loading...