Oh, das sind ja viele Antworten. Danke!
Ich werde versuchen auf die wichtigsten Punkte einzugehen...
Zitat von
jobo:
Ich kann mir nicht vorstellen, dass soetwas als Clientoperation in einem heterogenen Umfeld robust funktioniert. Allein schon verteilte Transaktionen innerhalb eines Systems können tückisch sein, abgesehen von der Synchronisationslogik.
Ich würde es bei heterogenen
DB mit einem Application Server versuchen.
Problem ist, dass sowohl Client1 als auch Client2 spontan mal ohne Internetzugang auskommen muss! Dass es dann natürlich zu Kollisionen kommen kann ist ja klar. Aber da haben wir das Konzept neuester Zeitstempel gewinnt. Nicht ganz toll - aber so ist es im Moment.
Zitat von
Lemmy:
Was ich mir vorstellen könnte: Du syncronisierst ja aktuell in 2 Ebenen: Einmal horizontal zwischen den Firebird-Installationen und einmal Vertikal zur MySQLDB. Wie wäre es die
MySQL als "Master" zu verwenden ...
Noch mal zur Verdeutlichung. Eine
MySQL-Master-
DB im Internet. Mehrere Clients (Firebird).
Die Clients haben einen Dienst, der alle 30 Sekunden die Datenbanken automatisch durchkämmt. Also nicht vom Benutzer angestossen.
Zuerst die eine, dann die andere Richtung.
Zitat von
Sx2008:
Der Hashvalue wird zusätzlich zu den Adressdaten in einem eigenen, indizierten Feld gespeichert...
Dies scheint mir zur als Zusatz sinnvoll. Wie soll man so Client->Master alle Sätze abgleichen.
Ein update eines Satzes müsste natürlich auch ein Update des MD5 nach sich ziehen.
Zitat von
gmc616:
Kurze Frage, damit ich das korrekt verstanden habe: Du synchronisierst EINE Firebird-
DB (Win-Client) mit EINER
MySQL-
DB (online), oder MEHRERE Firebird-
DB's (eine pro Client) mit EINER
MySQL-
DB?
Nochmals kurz. Mehrere Win-Arbeitsplätze (Clients mit Firebird Datenbank) und EINE
MySQL Master Datenbank.
Zitat von
gmc616:
Dein
DB-Konzept zur Synchronisation hört sich recht gut an.
Danke
Zitat von
gmc616:
... Das könnte ein System-Dienst auf dem lokalen
DB-Server übernehmen.
Passiert schon.
Zitat von
gmc616:
Dann brauchen deine Termine einen eindeutigen ID. Deshalb verpasst du den Terminen neben dem Zeitstempel, der die letzte Änderung des Termins beschreibt (nennen wir ihn Änderungsstempel), einen weiteren Zeitstempel, der die Erstellung des Termins beschreibt, mit einer zusätzlichen Kennung in welcher
DB der Termin erstellt wurde. Den nennen wir "Erstellstempel" oder einfach ID, dann das wäre dann einer.
Wichtig: Für beide Zeitstempel nutzt du die Zeit des jeweiligen
DB-Servers, nicht die des Clients! D.h. im
SQL-Statement Now()!!
Die zusätzlich
DB-Kennung deswegen, weil die Zeiten der beiden
DB's bzw. deren Server nicht zu 100% synchron sein werden.
Das könnte ein Knackpunkt sein. Also die Sätze haben eine eindeutige ID. Die ID ist über ein Generator gesetzt mit jeweils ein Offset (1 Mio.) je Client. D.h. der Nummernkreis der ID (1000000-1999999 Ist Platz 1, 2000000-2999999 Platz 2 usw.).
Brauche ich jetzt noch die zusätzliche
DB Kennung und wie meinst Du das genau mit dem Now(). Wenn ich lokal ein Now() mache habe ich ja die lokale Zeit. Du meinst bei jedem Insert die
MySQL Zeit einzustempeln (Internertzugang weg - Perfomance?) ???
Sorry aber ich habs net ganz verstanden.
Zitat von
Sir Rufo:
Hauptproblem bei der Synchronisierung via Zeitstempel bleibt aber die Auflösung des Zeitstempels.
Ein
MySQL Server schafft ja (je nach Hardware) mehr als einen Datensatz pro Millisekunde zu speichern.
xxx1 Client A schreibt Datensatz
xxx2 Client B bekommt die Datensätze geliefert (höchster Zeitstempel xxx)
xxx3 Client A schreibt Datensatz
Bei der nächsten Abfrage bekommt Client B aber nicht den 2. Datensatz von A geliefert, denn dieser Datensatz hat ja auch den Zeitstempel xxx obwohl er nach der Abfrage von Client B geschrieben wurde.
Somit müsste also die Abfrage nicht Zeitstempel > xxx lauten, sondern Zeitstempel >= xxx.
Damit bekommt man aber wieder ein entsprechenden Overhead, den man evtl. vermeiden möchte/muss.
Perfomance spielt hier so eine untergeordnete Rolle (Gefahr beim Löschen dass keine Sätze zurückkommen). Das größer gleich ist drin!
Zitat von
Sir Rufo:
Und da wartet schon die nächste Hürde:
Am Client wird die Uhrzeit 3h vor gestellt und schon würden alle jetzt gemachten Änderungen gewinnen.
Ich erkenne die Änderung der Systemzeit und hole bei jedem Sync (alle 30 Sekunden) die Systemzeit kurz vom
MySQL Server ab und vergleiche dies mit der aktuellen Uhrzeit. Damit dieser Fehler weitestgehend vermieden wird.
Zitat von
FredFesl:
Konfliktbehandlungen bekommst Du auch in den Griff, wenn Du dir eine Kopie der
DB ("Original") nach erfolgter Synchronisation erstellst und vor der nächsten Synchronisation die Daten mit dieser
DB-Version vergleichst: Hat sich ein zu ändernder Datensatz (Von 'A' nach 'B') zwischenzeitlich verändert, war die Änderung nicht exklusiv, es liegt dann also ein Konflikt vor. Du vergleichst also jeden DS VOR dem Abgleich mit dem Original. Damit erkennst Du zwar Konflikte, nicht jedoch, WER der Konfliktpartner ist.
Ich würde den ersten Weg wählen: Man hat auch eine sehr mächtige Änderungshistorie, was bei Geschäftsdaten nicht unerheblich ist. Du kannst dann auch Fragen beantworten, wie: "Wer hat denn damals den Ansprechpartner von Fa. Halmackenreuther geändert".
Kopien der Datenbanken möchte ich im Moment nicht machen. Die Idee ist gut, aber die Kollisionserkennung scheint mir im Moment nicht das Problem (außer Löschen, s.u.!).
Die Idee mit dem Erkennen der letzten Änderungen für Supportzwecke ist super!
WEITERE ANMERKUNGEN:
Eine Update Liste je Client wie von manchen gefordert hatten wir mal bei einer alten
DB Technik. Das war super unperfomant - könnte bei
FB jetzt besser gehen. Die Frage ist, ob man beides umsetzten sollte (Zeitstempel und Update-Liste). So könnte man Änderungen vielleicht sicherer erkennen. Sobald ein Satz entweder in der Update-Liste ODER über den Zeitstempel als geändert gilt ist er wirklich geändert. Mal überdenken...
Was ich mir noch vorstellen könnte, dass vielleicht der Satz (Termin) gelöscht wird und(!) auf der anderen Seite verändert??!! Möglicherweise wird diese Kollission nicht erkannt?
Ein Umbau auf ein Flag "IsDeleted" bei jedem Satz statt dem "echten" Löschen scheint mir auf alle Fälle sinnvoll. Aber dies ist natürlich auch nicht sofort erledigt bei ca. 50 Tabellen.
Gruß
Jürgen