Klaus Mock: "Synchronisations-Theorie"

Beitrag lesen

Hallo,

Um das Gehampel mit zwei ID-Feldern zu vermeiden, könntest du auch ein ID-Feld und ein Herkunftsfeld definieren. Das Herkunftsfeld definiert, welche dezentrale Datenbank zur Eingabe verwendet wurde. Wenn der Datensatz zur zentralen Datenbank hochgeladen wird, wird das Herkunftsfeld geändert und eine neue ID vergeben. Die Änderung wird dann zurückgesendet, bzw. generell komplett verteilt.

Wobei ich mich frage, was das bringen soll, wenn die Id's und das Herkunftsfeld geändert wird. Es geht doch einzig und allein darum, daß ein Datensatz eindeutig identifiziert werden kann, wobei verschiedene, ich nehm jetzt mal ein altmodisches Wort dafür, 'Nummerngeneratoren' für die ID verwendet werden. Und zwar für jede Datenbank ein eigener, wobei das Herkunftsfeld festlegt, welche Datenbank das jetzt war.

So, und nun wieder zum eigentlichen Problem.
Ich habe vor kurzem noch an einem Synchronisationsproblem gearbeitet, dessen Lösung wir irgendwan vor einem Jahr oder so diskutiert haben. Im Archiv wirst Du sicherlich noch fündig. Dabei haeb ich jedoch für jeden Datensatz in den dezentralen Datenbanken zwei ID's gepflegt, eine lokale ID und eine Server-ID. Ein Grund dafür war eigentlich,daß die dezentralen Datenbanken viel weniger Daten speichern mußten, da sie nur für das Remotesystem relevante Daten vom Server bekamen. Aber das ist eine andere Geschichte.
Egal, nehmen wir einmal an, wir verwenden ID + Herkunft für die Identifikation.

Ich verwende zwei Methoden, um geänderte Daten festzustellen. Am zentralen Server wird die Timestamp verwendet, und die Remotedatenbanken verwenden ein Änderungsflag. Der Grund dafür ist, daß ich mich nicht mit den wahrscheinlcih sicherlich vorhandenen Unterschieden der Systemzeiten auseinandersetzen will.
So, wie läuft nun _meine_ Synchronisation ab:

1.) Grundsätzlich startet nur das Remotesystem die Synchronisation.

2.) Hier werden zuerst alle Datensätze der zu synchronisierenden Tabellen ermittelt, wobei unerheblich ist, ob es neue oder modifizierte Datensätze sind.

3.) diese Daten werden in ein neutrales Format (Text-Dateien) gebracht und an den Server übertragen.

4.) Als Meta-Information wird noch die Remotehost-ID und der Zeitpunkt der letzten Synchronisation übertragen.

5.) Am Server wird zuerst einmal der aktuelle Timestamp ermittelt. Dieser Wert dient einerseits dazu, daß nur Daten, die bis zu diesem Wert in der Datenbank sind berücksichtigt werden, zum anderen wird er auch zurück an das Remotesystem übertragen, wo für die nächste Synchronisation als 'letzter Synchronisationszeitpunkt' abgelegt wird.

6.) dann wird jeder übertragene Datensatz des Remotesyystems eingepflegt. Das passiert so, daß zuerst anhand der ID (+Herkunftskennung) geprüft wird, ob er schon vrhanden ist. Wenn nicht, dann wird ein Insert geamcht, ansonst ein Update. Für die Bestätigung werden nun für jeden Datensatz eine Rückmeldung generiert, die praktisch dem Übertragungs-Datensatzformat entspricht.

7.) Ist das erledigt, werden am Server nun alle Datensätze ausgelesen, die zwischen dem letzten Synchronisationstzeitpunkt (das ist der vom Remotesystem übertragene Zeitpunkt) und dem unter 5.) ermittelten Timestamp geändert wurden. Diese Daten werde auch in das Übertragungs-Text-Format übergeführt.

8.) die so gesammelten Daten werden nun an das Remotesystem, gemeinsam mit dem unter 5.) ermittelten Timestamps übertragen.

9.) Am Remotesystem wird nun analog zum Server die Daten Satz für Satz in die Datenbank eingepflegt. Dabei wird wieder überprüft, ob es den Datensatz schon gibt und entsprechend ein Insert oder Updatestatement generiert.

10.) der Timestamp wird am Remotesystem lkal abgelegt, um bei der nächsten Synchronisation wiederverwendet zu werden.

Einige Anmerkungen zum Übertragungsformat. Ich habe, da mir am Remotesystem kein XML-Parser zur Verfügung steht, und weil bei der mir zur Verfügung stehenden Übertragungsgeschwindigkeit XML etwas zu viel Overhead hat ein einfaches TextFormat gewählt. Eine solche Übertragungsdatei siehtvielleicht so aus:

[TABELLENNAME]
ID:4711
HERKUNFT:123
NAME:ABCDEF
WERT:1234
MEMO:xyzdsdskdkjdsk
MODFLAG:1
[EOR]
ID:4712
HERKUNFT:123
NAME:ABCDEF
WERT:1234
MEMO:xyzdsdskdkjdsk
MODFLAG:1
[EOR]
...
[ANDERE_TABELLE]
ID:815
HERKUNFT:123
...
MODFLAG:1
[EOR]
[END_OF_FILE]

Als Antwort kommt dann vielleicht:

[TABELLENNAME]
ID:4711
HERKUNFT:123
MODFLAG:0
[EOR]
ID:4712
HERKUNFT:123
MODFLAG:2
[EOR]
ID:7773232
HERKUNFT:1
NAME:HDDJKHK
WERT:12323
MEMO:xyzdsdskdkjdsk
MODFLAG:0
[EOR]

[ANDERE_TABELLE]
ID:815
HERKUNFT:123
MODFLAG:0
[EOR]
[END_OF_DATA]

Mit dem Feld MODFLAG in der Antwort kann ich steuern, was lokal passieren soll. Wenn MODFLAG z.B. Null ist, dann ist alles gut gegangen, ich kann lokal bei diesem Datensatz das Flag auch zurücksetzen. Wenn es nicht Null ist, dann enthält es einen vereinbarten Fehlercode, auf dem halt irgenwie reagiert werden sollte. Der Datensatz muß in jedem Fall bei der nächsten Synchronisation wieder übertragen werden. Auhc bei einem Konfliktmanagment können diese Rückmeldungen wertvoll sein.

Die einzige Einschränkung m.E., die dieses Fromat, außer daß es nicht hip ist, hat, ist, daß es keine Tabelle geben darf, die EOR oder END_OF_DATA heißt;-)

Das Erzeigen und Verarbeiten läßt sich mit einem einfachen Zustandsautomaten lösen und ist eigentlich beliebig ausbaubar.

Außerdem ist der Mechanismus für die Übertragung per HTTP geeignet, wobei genau das eine der Absichten war.

So ich hoffe, das so halbwegs auf die Reihe gebracht zu haben, ohne vollkommen unverständlich zu sein. Aber wenn Du noch Fragen hast, weißt Du ja, wo Du mich findest;-)

Grüße
  Klaus