Datenbankabgleich Lokal <> Server

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Datenbankabgleich Lokal <> Server

Beitrag von MmVisual »

Hallo,

Ich habe eine Software, die Datenbank dazu läuft normalerweise auf meinem Server unter MariaDB. Und ich bin recht viel unterwegs, da habe ich keine gute Internetverbindung zur Datenbank. Also muss ich diese Datenbank "Mitnehmen". Dazu exportiere ich diese von MariaDB in eine SQLite Datenbank. (Ich bin zur Zeit der einzige der was ändert im Datenbestand.)
Die EXE läuft dann mit der SQLite Datenbank. Komme ich wieder zurück, so importiere ich die SQLite Daten zurück in MariaDB und kann damit dann wieder weiter arbeiten.

Soweit funktioniert das auch, ist nur ziemlich umständlich und lästig ständig dieses Importieren / Exportieren. Und wehe man hat einmal was in der Server Datenbank was dazu geschrieben und vergessen zuvor der letzte SQLite Stand zu importieren, dann darf man doppelt was machen :-/

Also benötige ich eine Abhilfe. Ich möchte gerne dass meine EXE in der Regel mit dem Server sich verbindet. Wenn der nicht vorhanden ist dass offline SQLite verwendet wird. Wenn ich dann Offline was ändere, dann soll das automatisch im Server nachgetragen werden. Ich würde dazu Funktionen schreiben wie "Daten offline bereit stellen" und "Offline Daten mit Server abgleichen".

Nun die große Frage:
Wie programmiert man das am Sinnvollsten?
In der Datenbank sind 22 Tabelle mit einigen tausend Datensätzen.
Es können jederzeit im Server Datensätze geändert werden und auch offline, die ich dann gerne zusammenführen möchte.
Wie macht man es wenn der gleiche Datensatz im Server und offline geändert wurden? Was wird dann zusammen geführt? Wohl müsste ich mir dazu merken welches Feld des Datensatzes jeweils geändert wurde?
Wenn im Server neue Datensätze entstehen, und auch Offline, die haben dann die gleiche ID (AutoInc Felder), da müssten auf dem Server wiederum die Datensäze angelegt werden, welche da jedoch eine eigene (andere) ID erhalten werden. Ist irgendwie auch schwierig.
Das Ziel sollte sein, dass so ein Abgleich gut funktioniert ohne dass zu viel Overhead entsteht.

Habt Ihr Lösungsvorschläge wie man dieses Problem klug umsetzen kann?

Möglichkeiten:
- Jede Tabelle erweitern mit zusätzlichen Feldern, mit Hilfe derer wird jede Änderung gekennzeichnet. (z.B. Memo-Feld, in der eine StringListe drin steht welches Feld, letztes Datum der Änderung, bzw. neue Datensatz und ein Datums-Feld der Änderung)
- Oder eine neue Tabelle die Änderungshistorie führt.

Das Problem haben sicher andere auch schon irgendwie lösen müssen. Gut wäre es wenn die Datenbank diesen Log automatisch führen könnte, den ich zum Nachführen der jeweils anderen Seite Server<>Offline nutzen könnte.

Dankeschön für die Ideen

Grüße Markus
EleLa - Elektronik Lagerverwaltung - www.elela.de

Thomas B.
Beiträge: 90
Registriert: Fr 2. Nov 2007, 13:32
OS, Lazarus, FPC: Win (L 1.0 FPC 2.6.0)
CPU-Target: 32Bit
Wohnort: Ulm

Re: Datenbankabgleich Lokal <> Server

Beitrag von Thomas B. »

Probier mal mit MariaDB eine automatische Master-Slave oder Multi-Source Replication aufzubauen. Das finde ich besser als den manuellen Abgleich mit einer SQLite DB.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von m.fuchs »

Gibt es nur einen Client oder müssen von mehreren aus die Synchronisationen durchgeführt werden?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Datenbankabgleich Lokal <> Server

Beitrag von mse »

MmVisual hat geschrieben:Das Problem haben sicher andere auch schon irgendwie lösen müssen. Gut wäre es wenn die Datenbank diesen Log automatisch führen könnte, den ich zum Nachführen der jeweils anderen Seite Server<>Offline nutzen könnte.

TmseSqlQuery von MSEgui bietet diese Möglichkeit. Die Daten werden vom Server geladen und danach kann die Verbindung unterbrochen werden. Änderungen werden in ein Journal geschrieben und können später an den Server übertragen werden. AFAIK bietet FCL-Sqldb mittlerweile eine ähnliche Funktion.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Datenbankabgleich Lokal <> Server

Beitrag von Warf »

Wie wäre es einfach regelmäßige SQL dumps zu machen und die SQL files dann über ein git repository zu managen.

Die meisten Änderungen entsprechen ja einfach nur dem einfügen oder löschen von Zeilen im SQL file, und damit kann git super umgehen

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Datenbankabgleich Lokal <> Server

Beitrag von MmVisual »

Dankeschön für die Antworten.
Ja, es gibt mehrere Clients. Meine Software ist Freeware und wird aktuell von einigen tausend Leuten aktiv genutzt. Ich habe mich damals für Lazarus / Zeos entschieden und bleibe auch dabei. SQL Dumps gehen nicht, da jeder der genannten Datenbanken sich eigene Dumps erstellt, die jeweils anders aussehen und doppelte (gleiche) ID's lassen sich damit nicht verwalten/zusammen führen.

Die MariaDB "Multi-Source Replication" hört sich gut an, ich lese mich da mal ein. Es spricht nichts dagegen dass auch meinem Laptop (für unterwegs) auch ein MariaDB Server läuft, der sich dann mit dem Server abgleichen kann, sofern die Verbindung besteht.

Grüße Markus.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von m.fuchs »

Wenn es bei so vielen Leuten läuft würde ich es nicht mit einem lokalen MariaDB-Server probieren. Das erhöht nur den Supportaufwand. Die Variante mit SQLite klingt da vernünftiger.
Die Datensynchronisation führst du dann mit deinem Programm selber durch. Das ist zwar aufwändig, aber du hast dann auch alles unter deiner Kontrolle.

Ein paar Dinge sind zu beachten:

  • Als Primärschlüssel solltest du GUID verwenden. Damit schließt du doppelte ID-Werte aus. Die können auch gut als Strings in Datenbanken abgelegt werden. Kostet zwar mehr Speicherplatz, aber das sollte ja kein Problem mehr sein.

  • Jeder Datensatz benötigt einen Timestamp seiner letzten Bearbeitung. Wenn ein Client sich mit dem Server synchronisiert, dann fragt er alle Datensätze seit dem letzten Sync ab. Und schreibt alle Datensätze die er selber seit dem erzeugt hat.

  • Wenn sich ein Datensatz im Server und im CLient geändert hat, dann musst du die Daten zusammenführen. Dafür gibt es verschiedene Möglichkeiten wie
    • Newest Win: Die jüngste Version des Datensatzes wird verwendet.
    • Server Win: Der Datensatz auf dem Server wird verwendet.
    • Man kann auch dem User beide Änderungen anzeigen und ihn wählen lassen.
Soweit erst mal meine Ideen zu der Aufgabe.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Datenbankabgleich Lokal <> Server

Beitrag von MmVisual »

Ja, die Idee mit der GUID hatte ich auch schon mal, aber in der zwischenzeit vergessen. Ich denke die GUID ist eine Einfache und recht Sichere Möglichkeit, bzw ich würde dann alle vergebene GUID in einer separaten Tabelle nochmals merken so dass garantiert jede GUID in allen Tabellen eindeutig wäre.

So sieht die Tabellenstruktur aktuell aus:
http://mmvisual.de/Hilfe/EleLa/Tutorial ... bellen.png
Die ForeignKey's existieren in Wirklichkeit nicht, die sind in der Tabelle-Grafik nur deshalb drin um zu verdeutlichen wie die einzelnen Datensätze zusammen hängen.
Und diese ID-Zuordnung muss natürlich nach dem Replizieren immer noch konsistent sein, ansonsten gibt es Datensatz-Laichen und die Daten sind dann scheinbar "verschwunden". Aktuell macht das die EXE auch schon alles.

PS: Die aktuelle Datenbank hat noch 2 Tabellen mehr und auch mehr Felder, diese Grafik sollte jedoch zum Verständnis ausreichen.

Bei MariaDB sind die Tabellen so angelegt:

Code: Alles auswählen

CREATE TABLE IF NOT EXISTS <tabelle...> (
  ID int(11) NOT NULL AUTO_INCREMENT,
: : :
  AendDatum timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (ID),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=0 ;

Bei SQLite muss ich selbst das AendDatum schreiben.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von m.fuchs »

MmVisual hat geschrieben:[...] ich würde dann alle vergebene GUID in einer separaten Tabelle nochmals merken so dass garantiert jede GUID in allen Tabellen eindeutig wäre.

Das ist unnötig, dass es zu einer Kollision zweier GUID kommt ist sehr, sehr unwahrscheinlich.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Datenbankabgleich Lokal <> Server

Beitrag von MmVisual »

Ja, ich kann die GUID auch aus allen Tabellen zusammen suchen. Außerdem reicht es aus wenn die GUID der Tabelle eindeutig ist. Wenn ich die DB Update und alle GUID automatisiert nachtrage, dann ist innerhalb weniger Sekunden der DB Update fertig. Wenn ich jedoch jede GUID in eine TStringList mir merke und überprüfe ob die nicht doppelt vorhanden ist (mit IndexOf()) dann dauert der DB Update 10 Minuten :shock: .
Also nutze ich die GUID in Zusammenhang mit der ID (AutoInc Feld) und damit ist das auch wieder eindeutig und ich kann nachvollziehen ob der Datensatz in beiden DB's der gleiche ist oder ob in beiden DB's ein neuer Datensatz erstellt wurde (= gleiche ID's / unterschiedliche GUID).

Das einzige: Ich weiß noch nicht genau wie ich gelöschte Datensätze entsprechend in der anderen DB nach pflege. Ich meine es muss ein Feld "Deleted" geben, was es kennzeichnet und der Datensatz darf nicht mehr tatsächlich gelöscht werden. Hat jmd dazu noch eine Idee?
Das Deleted hätte noch den charme, dass ich eine "Undo Deleted" realisieren könnte.

Grüße Markus
EleLa - Elektronik Lagerverwaltung - www.elela.de

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von Christian »

GUIDs sind dazu da einzigartig zu sein. Du brauchst nichts überprüfen.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von Socke »

MmVisual hat geschrieben:[...] Wenn ich jedoch jede GUID in eine TStringList mir merke und überprüfe ob die nicht doppelt vorhanden ist (mit IndexOf()) dann dauert der DB Update 10 Minuten :shock: .[...]

Wenn du GUIDs schon als Strings suchen musst, verwende wenigstens eine Hash-List 8)

In der Datenbank sollte die GUID auch binär und nicht als String abgelegt werden, damit der selbe Informationsgehalt in weniger Speicher abgelegt werden kann - und der Indexzugriff performant bleibt, siehe hierzu auch:
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von m.fuchs »

MmVisual hat geschrieben:Ja, ich kann die GUID auch aus allen Tabellen zusammen suchen. Außerdem reicht es aus wenn die GUID der Tabelle eindeutig ist. Wenn ich die DB Update und alle GUID automatisiert nachtrage, dann ist innerhalb weniger Sekunden der DB Update fertig. Wenn ich jedoch jede GUID in eine TStringList mir merke und überprüfe ob die nicht doppelt vorhanden ist (mit IndexOf()) dann dauert der DB Update 10 Minuten :shock: .
Also nutze ich die GUID in Zusammenhang mit der ID (AutoInc Feld) und damit ist das auch wieder eindeutig und ich kann nachvollziehen ob der Datensatz in beiden DB's der gleiche ist oder ob in beiden DB's ein neuer Datensatz erstellt wurde (= gleiche ID's / unterschiedliche GUID).

Das ist doch viel zu kompliziert. Vergiss Autoinc und nimm als ID (also Primärschlüssel) eine GUID. Dann musst du da gar nichts abgleichen. Welche Datensätze du dir holen musst, entscheidest du anhand des LastUpdated-Datums (oder wie auch immer du das nennst).

MmVisual hat geschrieben:Das einzige: Ich weiß noch nicht genau wie ich gelöschte Datensätze entsprechend in der anderen DB nach pflege. Ich meine es muss ein Feld "Deleted" geben, was es kennzeichnet und der Datensatz darf nicht mehr tatsächlich gelöscht werden. Hat jmd dazu noch eine Idee?

Genauso. Abgesehen davon ist die Anwesenheit eines DELETE-Statements in SQL-Befehlen häufig ein Anzeichen für ein Problem. Das sollte nur ganz selten eingesetzt werden, zum Beispiel um Datensätze aus riesigen (und häufig veränderten) Tabellen zu entfernen. hatte ich erst letztens als ich den Quellcode eines Kundenverwaltungssystems begutachten durfte. Beim Kündigen eines Vertrages wurde alle Daten aus der Datenbank abgeräumt. Ein Hinweis meinerseits auf Buchprüfungen und Aufbewahrungsfristen führte zu sehr hektischer Betriebsamkeit. :D
Also im Zweifel lieber stehenlassen die Daten und nur als gelöscht markieren.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von m.fuchs »

Socke hat geschrieben:In der Datenbank sollte die GUID auch binär und nicht als String abgelegt werden,

Gab es da nicht Probleme mit SQLite?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Datenbankabgleich Lokal <> Server

Beitrag von Socke »

m.fuchs hat geschrieben:
Socke hat geschrieben:In der Datenbank sollte die GUID auch binär und nicht als String abgelegt werden,

Gab es da nicht Probleme mit SQLite?

Dann legst du halt einen kombinierten Primärschlüssel über 2*8 Byte an.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten