Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken (https://www.delphipraxis.net/189026-umsetzung-einer-datensynchronisierung-zwischen-zwei-datenbanken.html)

RWarnecke 27. Apr 2016 11:18

Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Hallo zusammen,

ich habe die Aufgabe eine Synchronisierung zwischen einer SQLite Datenbank und den zwei Datenbanken FirebirdSQL oder MS-SQL zu realisieren. Die SQLite-Datenbank ist auf einem mobilen Gerät, welches im ersten Schritt über WLAN mit den entsprechenden Servern (FirebirdSQL oder MSSQL) die Daten synchronisieren soll. Dabei sollen lediglich nur die entsprechenden Daten synchronisiert werden, so dass es die Möglichkeit gibt die Daten auch Offline zu nutzen. Die Synchronisierung soll in beide Richtungen erfolgen.

Meine Frage, wie kann man jetzt am besten so eine Synchronisierung realisieren ? Dabei geht es nicht um Quelltext sondern um den Aufbau und den Ablauf.

Bambini 27. Apr 2016 11:38

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Zitat:

Zitat von RWarnecke (Beitrag 1336789)
Dabei geht es nicht um Quelltext sondern um den Aufbau und den Ablauf.

Wenn auf beiden Datenbanken gearbeitet wird, kommt man an einem Transaktionslog nicht vorbei.
Jede Datenbank protokolliert welcher Datensatz in welcher Tabelle ukModify, ukInsert oder ukDelete wurde, mit Datum und Uhrzeit.
Dieses Log wird dann beim Sync auf der anderen DB nachgeführt. Spannend wird es wenn es Kollisionen geben kann, d.h. auf beiden Seiten wurde am gleichen Datensatz geändert oder gar gelöscht. Um dies zu erkennen, muss beim Sync beide Transaktionslogs gelesen, verglichen und dann erst abgeglichen werden.

Auch unklar: Was passiert bei abhängigen Daten. Eine Eintrag in der Tabelle 1 hat 1:n Einträge in Tabelle 2. Jetzt löscht einer einen Eintrag in Tabelle 1, vermutlich werden die lösch-Statements für Tabelle 2 auch im Log stehen, aber wenn die andere Seite Einträge in Tabelle 2 hinzugefügt hat??

hstreicher 27. Apr 2016 11:40

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Also ich kenne da 2 Möglichkeiten

1) in die Records ein Flag einbauen "Muss syncronisiert werden" geht aber nur für 1:1 Also 1 Mobilgeräte auf eine Grosse DB

2) Trigger die Geänderte Daten (oder Referenzen darauf) in eine "ToDo" Tabelle schreiben , hier wären bei mehreren Syncronisationspartnern dann eben ein Eintrag pro Ziel notwendig

mfg Hannes

Bambini 27. Apr 2016 11:44

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Zitat:

Zitat von hstreicher (Beitrag 1336797)
1) in die Records ein Flag einbauen "Muss syncronisiert werden" geht aber nur für 1:1 Also 1 Mobilgeräte auf eine Grosse DB

Wie klappt das bei ukDelete?

hstreicher 27. Apr 2016 11:49

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
wie bei DBase und Co ein Deleted Flag und erst nach der Sync löschen

aber die 2 Lösung ist eh besser

Rollo62 27. Apr 2016 15:10

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Käme das Briefcase Modell in Frage ?
http://docwiki.embarcadero.com/InterBase/XE7/en/Using_the_Briefcase_Model

http://www.drbob42.com/examine/examin64.htm
https://en.wikipedia.org/wiki/Briefc...oft_Windows%29

Rollo

mm1256 27. Apr 2016 17:29

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Hallo Rolf,

ClientDataset ist schon mal ein guter Gedanke. Die Tücke steckt aber im Detail, wenn die Synchronisierung in beide Richtungen erfolgen soll. Doch das ist dir ja wohl selber bewusst, sonst würdest du nicht fragen. Also, ich hatte so eine Synchronisierung jahrelang (2003 bis ca. 2010) im Einsatz. Zwar nur mit Notebooks (wo ich wenigstens die selbe Datenbank aufsetzen konnte) aber die Probleme sind die gleichen. Mit einem einzelnen Flag pro Datensatz (ich hatte hierzu ein Feld Timestamp der letzten Änderung im Einsatz) kommt man nicht weit. Das ist bestenfalls für die Performance-Optimierung beim Abgleich zu gebrauchen. Es muss jede Änderung pro Datensatz und Datenfeld protokolliert werden. Idealerweise in einer DB die dann beim Synchronisieren abgearbeitet wird. Und selbst dann kann es noch Ärger geben, wenn z.B. beim gleichen Datensatz das selbe Feld von unterschiedlichen Usern verändert wurde.

Wer gewinnt? Den User fragen wäre eine mögliche Variante, doch selbst das müsste man dann wieder protokollieren, denn sonst zieht deine Hotline die A-Karte und Ärger ist irgendwann vorprogrammiert. So viel ist nach meiner Erfahrung sicher.

Abhilfe: Datentransfer nur in einer Richtung. Wenn jemand unbedingt beide Richtungen haben will, dann soll er besser Geld in eine Online-Lösung (Teamviewer, Remote-Desktop...) investieren, als in eine Datenbank (Sonder-)Programmierung die sowieso langfristig gesehen mehr kostet.

Darum ein gut gemeinter Rat: die Finger von der Umsetzung "in dieser Art und Weise" lassen. Es gibt genügend fertige Alternativen.

BUG 27. Apr 2016 19:53

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Meiner Meinung nach ist es oft ein Fehler, solche Sachen von der technischen Seite anzugehen (und nachträglich irgendwo reinzufummeln).

Was sind das für Daten (semantisch)? Welche davon können geändert werden? Welche Teile der Daten sollen nur atomar/zusammen geändert werden? Was ist der konsistente Zustand / ein Konflikt. Wie gehe ich mit einem Konflikt um? Wer kann Konflikte beheben (betrifft ja auch Rechteverwaltung)? Gibt es Rollen oder Operationen, die Vorrang gegenüber anderen haben?

Danach kann man überlegen: Welche zusätzlichen Daten brauche ich, um Konflikte zu erkennen und zu evtl. beheben. Dabei sollte man auch daran denken, das z.B. Zeitstempel in verteilten Systemen selten eine gute Lösung sind.

Sir Rufo 27. Apr 2016 20:32

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Statt eines Zeitstempels nimmt man eine RowVersion und inkrementiert diese bei jeder Änderung des Datensatzes. (MSSQL hat den Datentyp schon integriert und inkrementiert auch automatisch)

Server
  • ID int
  • Version RowVersion
  • Deleted bool
Client
  • ID GUID
  • Version RowVersion
  • Deleted bool
  • RemoteId int (Server ID)
  • RemoteVersion RowVersion (Server Version)
Mit den Informationen lassen sich neue, gelöschte und geänderte Datensätze finden sowie Änderungskollisionen feststellen.

jobo 27. Apr 2016 20:42

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Zitat:

Zitat von BUG (Beitrag 1336857)
Meiner Meinung nach ist es oft ein Fehler, solche Sachen von der technischen Seite anzugehen

Sehr gut, ich würde aber "ausschließlich technisch" sagen.
"Was brauche ich eigentlich?", diese Frage dürfte am Anfang stehen.

- gelöschte Datensätze
Sollte kaum der Fall sein. Sobald es um geschäftliche Dinge geht, ist man schnell verpflichtet, aufzubewahren. Notfalls tut es ein Löschflag.
- konkurierende Änderung, auch eher selten, Klassiker wäre die Außendienst-Verkaufssoftware. Hier gibt es meist aus unterschiedlichsten Gründen Vertriebsregionen und genau festgelegte Kundenkreise, da konkurriert nichts. Eine Grundsätzliche Ausnahme wäre der Verkauf von physikalisch beschränkt vorhandenen Dingen. (Elektroautoprämie) Dafür wäre ein Offlinesystem aber wirklich nicht geeignet.

Damit wären die "schlimmsten" Fälle beispielsweise wegdefiniert. Eine Implementierung muss also nicht so umfangreich ausfallen.

Und ja, dafür gibt es auch fertige Bibliotheken. Ich hab mir mal sowas angeschaut. Eines hat mir sehr gut gefallen. Der Kunde wollte dafür aber nichts zahlen (Lizensierungskosten, laufende Kosten), es war kommerziell kostenpflichtig. Das System (generisch) hat zur Abbildung der Funktionalität ca 40 eigene Tabellen verwendet, wenn ich mich richtig erinnere. Soviel zum Thema 1 Flag - Lösung.

BUG 27. Apr 2016 20:56

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Zitat:

Zitat von jobo (Beitrag 1336861)
ich würde aber "ausschließlich technisch" sagen.

Stimmt schon natürlich :stupid:

Zitat:

Zitat von Sir Rufo (Beitrag 1336860)
Statt eines Zeitstempels nimmt man eine RowVersion und inkrementiert diese bei jeder Änderung des Datensatzes.

Damit lässt sich schon etwas anfangen. Aber dafür müssen die Daten halt passend strukturiert sein und man muss sich vorher Gedanken gemacht haben, was passieren kann.

Namen wir an, wir haben eine Datenbank und jeder Nutzer hat ein Punktekonto (id, punkte). Während der Client getrennt ist, überweist dieser 5 Punkte von Alice an Bob. Auf dem Onlineserver bekommt Bob 10 Punkte für gutes Benehmen gutgeschrieben.
Wenn ich dann nicht auch die Transaktionen als neue Spalte gespeichert haben, dann kann ich Fehler zwar erkennen, für die Fehlerbehebung (selbst manuelle) sieht es düster aus.

madas 27. Apr 2016 21:02

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Zitat:

Zitat von BUG (Beitrag 1336862)
Namen wir an, wir haben eine Datenbank und jeder Nutzer hat ein Punktekonto (id, punkte). Während der Client getrennt ist, überweist dieser 5 Punkte von Alice an Bob. Auf dem Onlineserver bekommt Bob 10 Punkte für gutes Benehmen gutgeschrieben.
Wenn ich dann nicht auch die Transaktionen als neue Spalte gespeichert haben, dann kann ich Fehler zwar erkennen, für die Fehlerbehebung (selbst manuelle) sieht es düster aus.

Für diesen Fall kann man ja History-Tabelle mitführen. :D

Sprich wenn (Client.RowVersion > Client.RemoteRowVersion) && (Server.RowVersion > Client.RemoteRowVersion) dann müsste man mit den History-Tabellen arbeiten bzw. diese beim Abgleich mit einbeziehen.

RWarnecke 27. Apr 2016 21:07

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
Hallo zusammen,

danke für die vielen Antworten. Ich glaube, dass ich für mein Vorhaben das nochmal überdenken muss, ob ich wirklich eine Synchronisierung in zwei Richtungen realisiere. Nach den ganzen Posts, tendiere ich immer mehr zu einem Live System, wo das mobile Gerät direkt über einen Dienst auf die Datenbank zugreift.

Aber ich bin immer noch für weitere Vorschläge offen, da es ja bis jetzt immer noch irgendwo einen Haken gibt. Wobei ich sagen muss, je länger ich darüber nachdenke, es aus meiner Sicht keine hundertprozentige Lösung für die Konstellation SQLite <--> FirebirdSQL und SQLite <--> MSSQL gibt. Da die Software, die auf dem Desktop genutzt wird beiden Datenbanken unterstützt (MSSQL und FirebirdSQL).

Sir Rufo 27. Apr 2016 21:10

AW: Umsetzung einer Datensynchronisierung zwischen zwei Datenbanken
 
@BUG

Es gibt Stammdaten (Alice, Bob), Bewegungsdaten (5 Punkte von Alice nach Bob, 20 Punkte an Bob) und dann die kumulierten Daten (Saldo für Alice, Bob).

Die Stammdaten und Bewegungsdaten werden zwischen den Systemen ausgetauscht. Die kumulierten Werte bildet jedes System selber.

Nur so zum Verständnis, ein Update sieht dann z.B. so aus
Delphi-Quellcode:
Query.SQL.Text := 'UPDATE person SET version = version+1, deleted = :deleted, name = :name WHERE id=:id AND version = :version';
Query.ParamByName('id').Value := aPerson.Id;
Query.ParamByName('version').Value := aPerson.Version;
Query.ParamByName('deleted').Value := aPerson.Deleted;
Query.ParamByName('name').Value := aPerson.Name;

Query.ExecSQL;

if Query.RowsAffected = 0 then
  raise EConcurrencyException.Create('Datensatz wurde schon vorher geändert');


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:35 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz