Bidirektionaler Abgleich SQLite <-> MariaDB ?

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Hallo zusammen,

ist es möglich, zwei Datenbanken, und zwar MariaDB und SQLite, bei Bedarf miteinander programmatisch abzugleichen ? Momentan arbeite ich an einem Auswertungs-Programm in PyQt und habe jetzt damit begonnen, eine MariaDB zu integrieren. Diese Datenbank habe ich gewählt, weil ich vorhabe, diese DB irgendwann auch mal im Netz oder online verfügbar zu machen.

Die MariaDB hindert mich aber daran, dieses Programm auch offline zu verwenden und ich frage mich, ob es nicht sinnvoller wäre, im Programm mit einer SQLite-DB zu arbeiten und diese dann bei Bedarf mit der "Online"-MariaDB abzugleichen. Ich habe aber noch keine grosse Ahnung von Datenbanken und würde gerne wissen, ob ein solcher Abgleich ohne sehr grossen Aufwand möglich wäre und ob es bezüglich der Verlagerung der DB-Logik (Fremdtabellen-Handling) in die Datenbank bei SQLite irgendwelche Einschränkungen gibt.

Vile Grüße
mephisto-online
BlackJack

@mephisto-online: So ein Abgleich müsste von Dir programmiert werden und dabei solltest Du keine „Hilfe” von der jeweiligen DB erwarten. Grundsätzlich also möglich und auch von den konkreten DBs unabhängig, aber Du müsstest Dir halt die Mühe machen die Daten entsprechend zu gestalten, also zum Beispiel keine automatisch von der DB generierten Schlüssel, sondern solche bei denen *Du* garantieren kannst, dass sie global eindeutig sind.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@mephisto-online: zwei Datenbanken parallel zu betreiben ist sicher keine gute Idee. Wie will man da Konsistenz garantieren? Ich verstehe auch nicht, warum es nicht möglich sein sollte, zu Test-Zwecken lokal eine MariaDB zu installieren?
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@BlackJack
BlackJack hat geschrieben:@mephisto-online: So ein Abgleich müsste von Dir programmiert werden und dabei solltest Du keine „Hilfe” von der jeweiligen DB erwarten.
Dabei erwarte ich auch keine Hilfe von der DB. Ist mir klar, dass ich das selbst programmieren muss. Ich nehme an, das man das mit SQL machen kann ?
BlackJack hat geschrieben: ... also zum Beispiel keine automatisch von der DB generierten Schlüssel ...
Ohje ! :shock: Soweit bin ich noch garnicht ! Habe wohl sowas schon gesehen, aber habe es als eher die "höhere Schule" erst mal ignoriert, weil ich nicht glaube, dass ich es brauche. Eigentlich generiere ich die Schlüssel selbst. :?

Sind denn die "Engines" (ISAM, Inno) in beiden Datenbanken gleich ? Für Fremdschlüsselbenutzung brauch ich ja, wie ich das verstanden habe, InnoDB-Records (ich hoffe, dass ich die richtige Datenbank-Terminologie benutzte, ansonsten bitte meckern !). Das ist also in SQLite auch möglich ?

Könnte man denn mit überschaubarem Aufwand generell auch eine Umschaltung zwischen den beiden Datenbanken im Programm vorsehen ? Bei grösseren Datenbank-Recherchen könnte SQLite ja dann doch etwas langsam sein.

Grüße
mephisto-online
BlackJack

@mephisto-online: SQL spielt dabei eine Rolle, wenn man denn direkt selber SQL schreibt und keine Bibliothel wie `SQLAlchemy` verwendet um von den konkreten DBMS zu abstrahieren. Aber die Logik für so einen Abgleich müsste man in Python schreiben.

Schlüssel generiert man normalerweise nur selbst wenn man das tatsächlich muss, zum Beispiel um zu garantieren das die global eindeutig sind, oder wenn eine Tabelle schon einen brauchbaren natürlichen Schlüssel in den Daten besitzt. Denn ansonsten ist das generieren von den üblichen Schlüsseln unnötige Arbeit und eine unnötige Fehlerquelle.

Die ”Engines” sind natürlich nicht gleich, sonst wären es ja nicht verschiedene Datenbanken. Bei MySQL sieht man ja dass sogar ein DBMS verschiedene Engines implementieren kann. Was verstehst Du unter Fremdschlüsselbenutzung? Fremdschlüssel kann man mit jeder relationalen Datenbank benutzen, sonst wäre es keine relationale Datenbank wenn man die Tabellen nicht in Beziehung setzen würde. Die InnoDB-Engine braucht man bei MySQL um Transaktionen verwenden zu können was ISAM soweit ich weiss nicht kann. War früher jedenfalls so.

Wenn man nichts spezfisches von einem SQL-DBMS nutzt, dann kann man die relativ leicht austauschen.

Ob SQLite schneller oder langsamer als MySQL ist kann man so pauschal nicht sagen. Jedes DBMS hat seine Vor- und Nachteile, Stärken und Schwächen.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@mephisto-online: es geht hier nicht um »Fremdschlüsselbenutzung«, sondern um ganz normale Primary-Keys, die normalerweise von der Datenbank automatisch hochgezählt werden, und als Referenz in anderen Tabellen benutzt werden. Woher hast Du Deine Information, dass SQLite langsamer sei als MariaDB???
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@Sirius3
Sirius3 hat geschrieben:@mephisto-online: zwei Datenbanken parallel zu betreiben ist sicher keine gute Idee. Wie will man da Konsistenz garantieren? Ich verstehe auch nicht, warum es nicht möglich sein sollte, zu Test-Zwecken lokal eine MariaDB zu installieren?
Das habe ich ja im Moment so gemacht. Wenn ich das Programm aber mobil (Android-Tab) oder bei Bekannten benutzen möchte und dann immer erst nen DB-Server installieren muss, finde ich das nicht so toll.

Und was die Konsistenz angeht, stelle ich mir das halt so vor, dass ich mit dem Programm entweder mit einem etwas älteren Stand der "Original"-Datenbank (MariaDB) oder halt mit einem aktuell abgeglichenen arbeiten kann. Schreibenden Zugriff auf die "Online"-Master-MariaDB werde auch nur ich (oder irgendwann ein Webserver) haben.

@BlackJack
BlackJack hat geschrieben:SQL spielt dabei eine Rolle, wenn man denn direkt selber SQL schreibt und keine Bibliothel wie `SQLAlchemy` verwendet um von den konkreten DBMS zu abstrahieren. Aber die Logik für so einen Abgleich müsste man in Python schreiben.
Wäre in einem solchen Fall u.U. der Einsatz von SQL-Alchemie vielleicht doch ne gute Idee ? Ich möchte das halt wissen, BEVOR ich mir viel Arbeit mit einer sich irgendwann als unglücklich erweisenden Lösung mache. Die Logik für den Abgleich muss ich natürlich selbst codieren, das ist mir klar. Was allerdings Transaktionen sind, das habe ich wohl auch schon gelesen, habe ich aber noch nicht do ganz kapiert. Ich weiss nur, dass QSqlRelationalTableModel wohl mit MySQL die InnoDB-Engine benötigt (habe ich jetzt aber gerade nicht wiedergefunden). Ich muss da auch erst noch ne Menge lesen, bevor ich ich zu viel Boolshit schreibe. Mir geht es ja hier erstmal nur um die "Marschrichtung".

@Sirius3
Sirius3 hat geschrieben: es geht hier nicht um »Fremdschlüsselbenutzung«, sondern um ganz normale Primary-Keys, die normalerweise von der Datenbank automatisch hochgezählt werden, und als Referenz in anderen Tabellen benutzt werden.
Ok, die Primary-keys sind ja wohl was Grundsätzliches, oder ? Mit »Fremdschlüsselbenutzung« (ok, wahrscheinlich falsches Wort) meine ich, dass ich in einem Datensatz z.B. den Primary-Key einer Städte -Tabelle eintage. Ok, das möchte ich aber jetzt hier nicht diskutieren, dafür müsste ich erst noch ein bisschen mehr lesen und ausprobieren. Das ist ja auch hier jetzt nicht meine Frage.

Und das SQLite langsamer sein soll, habe ich halt immer wieder im Internet gelesen, kann ja sein, dass das nicht stimmt, keine Ahnung.

Für diese Unterhaltung bin ich Euch echt dankbar ! :D

Grüße
mephisto-online
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wie Sirius3 schon gesagt hat: der eigentliche Knackpunkt ist der Online-Offline Betrieb. Wenn du sicher bist, dass *nie* zwei Benutzer unabhängig voneinander den gleichen Datensatz anlegen bzw. editieren kann das funktionieren.

Aber die ganzen RDBMS sind nun mal nicht für mal abhängig mal unabhängig agierende Instanzen ausgelegt.

Eine DB, die so was sehr gut kann, ist z.B. CouchDB. Ist aber eine Dokumenten-orientierte DB, kein RDBMS. CouchDB hätte für deine Anwendung aber noch den Charme, dass es mit PouchDB eine JavaScript-Clone gibt, der z.B. für die lokale App auf dem Smartphone eine gute Wahl wäre.

Gruß, noisefloor
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@noisefloor
noisefloor hat geschrieben:Wenn du sicher bist, dass *nie* zwei Benutzer unabhängig voneinander den gleichen Datensatz anlegen bzw. editieren kann das funktionieren.
Verhindert das nicht schon die Datenbank, beim Anlegen mit dem eindeutigen Primary-Key und beim Editieren mit der Sperrung des Datensatzes ?
noisefloor hat geschrieben:Aber die ganzen RDBMS sind nun mal nicht für mal abhängig mal unabhängig agierende Instanzen ausgelegt.
Das wäre technisch ja auch fast nicht möglich oder zumindestens enorm aufwendig ! Bei mir soll lediglich irgendwann mal eine Instanz der DB auf einem Webserver laufen (im Moment noch zu Hause im Netz). Mein Programm soll ein möglichst aktuelles "Snapshot" davon offline (in Form einer SQLite-Datenbank) verfügbar haben und um mit den Daten in diesem "Snapshot" zu arbeiten, bzw. gegebenenfalls auch Datensätze anzulegen oder zu editieren. Diesen "Snapshot" , d.h. geänderte oder hinzugefügte Datensätze darin), möchte ich dann gegebenenfalls mit der Online-Instanz der MariaDB abgleichen können.
noisefloor hat geschrieben:Eine DB, die so was sehr gut kann, ist z.B. CouchDB. Ist aber eine Dokumenten-orientierte DB, kein RDBMS. CouchDB hätte für deine Anwendung aber noch den Charme, dass es mit PouchDB eine JavaScript-Clone gibt, der z.B. für die lokale App auf dem Smartphone eine gute Wahl wäre.
Danke für den Tip ! Gut zu wissen. Werde wohl in Zukunft noch einiges mit Datenbanken machen. Bislang habe ich DBs immer nur genutzt.

Grüße
mephisto-online
BlackJack

@mephisto-online: Natürlich verhindert das *die* Datenbank wenn beide Benutzer mit der einen, selben Datenbank arbeiten; aber Du willst ja gerade zwei unabhängige DBs verwenden, und da kann die eine Instanz nicht verhindern oder überhaupt mitbekommen was bei der anderen gerade passiert.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@BlackJack
BlackJack hat geschrieben:...und da kann die eine Instanz nicht verhindern oder überhaupt mitbekommen was bei der anderen gerade passiert.
Das ist mir klar ! Es wäre aber für mich wichtig, einen "Snapshot" der Original-Instanz offline (z.B. in einer SQLite-DB) mitnehmen und darin Änderungen vornehmen könnte, die ich, wenn ich wieder and die Original-Instanz drankomme, dort einbringen könnte. Aber vielleicht ist das ja auch gar nicht möglich und Träume sind Schäume. :?
BlackJack

@mephisto-online: Wie gesagt, so etwas müsstest Du Dir selber programmieren. Mit allem was dazu gehört, also zum Beispiel auch erkennen von Konflikten und eine irgendwie geartete Auflösung selbiger. Das ist nicht ganz so trivial und es kommt halt darauf an was genau man machen möchte.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@BlackJack
BlackJack hat geschrieben:Wie gesagt, so etwas müsstest Du Dir selber programmieren.
Das würde ich mir schon zutrauen ...
BlackJack hat geschrieben:Mit allem was dazu gehört, also zum Beispiel auch erkennen von Konflikten und eine irgendwie geartete Auflösung selbiger.
In meiner noch laienhaften Vorstellung würde ich da folgendermassen vorgehen:

- In meinem Programm ein Snapshot der Original-Datenbank in der SQLite-DB erzeugen.
- Im Offline-Modus die Änderungen protokollieren.
- Wenn ich wieder an die Original-Datenbank drankomme, diese offline schalten
- Mit meinem Programm die protokollierte Änderungen dort einbringen.
- Original-Datenbank wieder online schalten.
- Die Datenbasis meines Programms auf die Original-Datenbank umschalten, solange ich drankomme.

Es müsste doch reichen, wenn ich dafür sorge, dass während der Änderungen niemand anderes drauf zugreifen kann, oder ?

Grüße
mephisto-online
BlackJack

@mephisto-online: So grob klingt das so als könnte man das so machen. Offline schalten wäre nur bei Datenbanken nötig die keine Transaktionen unterstützen, also zum Beispiel bei MySQL/MariaDB mit ISAM-Engine. Und man muss natürlich noch mit Konflikten irgendwie umgehen, oder wenn man die einfach ignoriert, zumindest sicherstellen und am besten auch dokumentieren dass das in Ordnung ist und warum.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@BlackJack
BlackJack hat geschrieben:@mephisto-online: So grob klingt das so als könnte man das so machen.
Sehr gut ! Dann wird die Sache ja langsam klarer !
BlackJack hat geschrieben:Offline schalten wäre nur bei Datenbanken nötig die keine Transaktionen unterstützen, also zum Beispiel bei MySQL/MariaDB mit ISAM-Engine.
OK ! Noch mal kurz zu "Transaktionen", da ist mir noch nicht ganz klar, was das genau ist.
Wikipedia schreibt
Transaktionen kommen meist bei Datenbanksystemen zum Einsatz. Fehlerhafte Transaktionen müssen abgebrochen und die bisherigen Änderungen in der Datenbank rückgängig gemacht werden, so dass sie keine Auswirkungen auf den Zustand der Datenbank haben.
Und das geht mit der ISAM-Engine nicht ? Dann kann ich die bei Mehrbenutzer-Systemen überhaupt nicht benutzen (wenn, dann nur für statische Tabellen ? Sowas habe ich nämlich auch in Form von Zeitzonen, die sind nämlich ISAM-mässig vorgesehen) ?

Und was sind genau "Fehlerhafte Transaktionen" ? Beispiel ?

Grüße
m-o
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

eine Transaktion ist eine oder eine Gruppe von Datenbankoperation (Schreiben, Ändern, Löschen etc.), die explizit ausgeführt werden müssen (Befehl "commit") und bei Bedarf auch rückgängig gemacht werden können (Befehl "rollback"). ISAM ist transaktionsfrei, d.h. alle Befehle werden sofort ausgeführt. Das hat _nichts_ mit der Mehrbenutzerfähigkeit zu tun!

Transaktionen sind immer dann nützlich, wenn mehrere Datenbank-Operation hintereinander ausgeführt werden sollen, die voneinander abhängen. Z.B. wenn eine Zeile in Tabelle A und eine in Tabelle B geändert werden soll. Es müssen aber auf jeden Fall beide Änderungen gemacht werden. Dann packt man das in eine Transaktion, was dann garantiert, dass die Operationen "komplett oder gar nicht" ausgeführt werden.

SQLite kennt Transaktion, man kann die DB auch in den autocommit-Modus setzen.

Gruß, noisefloor
BlackJack

@noisefloor: Es hat mittelbar aber schon mit Mehrbenutzerbetrieb zu tun, denn genau darin liegt ja oft der Grund warum in einer Transaktion ein Fehler auftritt und zurück gerollt werden muss.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@noisefloor
Dann sind Transaktionen bei mir wichtig ! Brauche bei neuem Stammsatz (Tabelle 1) z.B. oft auch einen neuen Eintrag in eine oder mehrere weitere Tabellen auf den ich im Stammsatz verweise, also ein commit mit (neuer Datensatz und neuer Eintrag in Tabelle 2 ... 3 ... 4), die zusammengehören und es ist sicherlich hilfreich, wenn man nach erfolgtem commit noch mal nachchecken und bei Fehlern das Ganze auch dann wieder zurücknehmen kann. Langsam kapier ich das.

@BlackJack
Das kann ich mir vorstellen, dass es da bei Mehrbenutzer-Zugriff (z.B. Webserver) zu fehlerhaften Transaktionen kommen kann !

Und ich hoffe, dass ich recht in der Annahme gehe, dass eine Datenbank immer über eine Engine läuft. Die Transaktions-Facility wird ja wohl auch nicht stören, wenn es darin auch Tabellen gibt, die niemals (von Benutzern) verändert werden (bei mir u.A. Timezones). Momentan habe ich die aber sowieso in einer anderen, eigenen DB. Die könnte dann bei der MariaDB wohl auch mit der ISAM-Engine laufen.

Wenn ich da noch was falsch sehe, bitte meckern !

Ansonsten bin ich schon dran, meine ersten Models und Views mit PyQt und SQLite3 zu basteln. Klappt, wie von Python und PyQt gewohnt, erstaunlich gut. Und die SQLite ist macht auch brav alles, was vorher mit der MariaDB schon problemlos ging.

Ich danke Euch erst mal ! Ohne Euch hätte ich das nicht so schnell gerallt.

Grüße
m-o
bfm
User
Beiträge: 88
Registriert: Donnerstag 14. März 2013, 09:42

mephisto-online hat geschrieben: Dann sind Transaktionen bei mir wichtig ! Brauche bei neuem Stammsatz (Tabelle 1) z.B. oft auch einen neuen Eintrag in eine oder mehrere weitere Tabellen auf den ich im Stammsatz verweise, also ein commit mit (neuer Datensatz und neuer Eintrag in Tabelle 2 ... 3 ... 4), die zusammengehören und es ist sicherlich hilfreich, wenn man nach erfolgtem commit noch mal nachchecken und bei Fehlern das Ganze auch dann wieder zurücknehmen kann. Langsam kapier ich das.
Stell dir mal eine Bank vor. Die Bank führt Überweisungen aus. Eine Überweisung spricht immer mindestens zwei Konten an. Ein Konto wird im Soll gebucht, das andere im Haben. Ist das Sollkonto gebucht und läuft dann beim Habenkonto etwas schief, so muss 100%ig gewährleistet sein, dass auch die Buchung auf dem Sollkonto zurückgenommen wird. Ansonsten hat die Bank mal irgendwann ein Problem. Spätestens zum Bilanzstichtag, weil die Bilanzsummen nicht aufgehen.
mephisto-online hat geschrieben: @BlackJack
Das kann ich mir vorstellen, dass es da bei Mehrbenutzer-Zugriff (z.B. Webserver) zu fehlerhaften Transaktionen kommen kann !
Gleichzeitiges Lesen in einer Datenbank ist ja kein Problem. Probleme gibt es nur, solange in die Datenbank geschrieben wird. Da kommt es darauf an, wie die Sache im Datenkbanksystem implementiert ist. Wird komplett die ganze Datenbank gesperrt (wie das wohl SQlite macht), werden einzelne Tabellen gesperrt oder geht das Datenbanksystem soweit, dass es nur einzelne Datensätze sperrt (zB DB2). Oder das Datenbanksystem macht gar nichts und dann gibt es unter Umständen halt mal einen "Datenschiefstand".

mfg
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@bfm
Kann man denn mehrere commits zurückrollen, d.h. gibt es sowas wie ne history ?
Antworten