Aufrechterhaltung der referenziellen Integrität zwischen einem mobilen Client und einem Server


21

Ich habe also ein relativ einfaches System. Ein mobiler Client erstellt Datensätze in einer SQLite-Datenbank, die ich mit einem Remote-SQL-Server synchronisieren möchte (der mit anderen mobilen Clients gemeinsam genutzt wird) . Wenn ich also einen neuen Eintrag in der SQLite-Tabelle des Telefons erstelle, übertrage ich diese Änderung über eine RESTful-API an meinen Remote-Service. Das Problem, das ich habe, ist, wie ich die Primärschlüssel bestelle, damit die Daten nicht kollidieren (dh ein Datensatz im Telefon hat den gleichen Primärschlüssel wie ein völlig anderer Datensatz auf dem Server). Was ist die übliche "Best Practice" zum Verweisen auf den Datensatz auf dem Client und zum Verweisen auf denselben Datensatz auf dem Server?


1
Die übergeordnete Idee wäre, dass der Client als Cache für den Webserver fungiert, wobei Änderungen im Client erstellt und dann auf den Webserver übertragen werden
JoeCortopassi,

Antworten:


22

In der Regel wird Ihre Datenbank mit uniqueidentifierSchlüsseln strukturiert (manchmal als UUIDs oder GUIDs bezeichnet). Sie können sie an zwei Stellen erstellen, ohne realistische Angst vor Kollisionen zu haben.

Als Nächstes muss Ihre Mobile-App Faktentabellen vom Server synchronisieren, bevor Sie neue Zeilen erstellen können. Wenn Sie neue Zeilen erstellen, geschieht dies lokal. Wenn Sie erneut synchronisieren, werden dem Server neue Zeilen hinzugefügt. Sie können dasselbe auch mit Aktualisierungen und Löschungen tun.

Zum Verfolgen von Einfügungen benötigen Sie einen erstellten Zeitstempel in Ihren Zeilen. Um Aktualisierungen zu verfolgen, müssen Sie einen LastUpdate-Zeitstempel in Ihren Zeilen verfolgen. Zum Verfolgen von Löschvorgängen benötigen Sie eine Tombstone-Tabelle.

Beachten Sie, dass Sie bei einer Synchronisierung den Zeitversatz zwischen dem Server und dem mobilen Gerät überprüfen und eine Methode zum Lösen von Konflikten benötigen. Einfügungen sind keine große Sache (sie sollten nicht in Konflikt stehen), aber Aktualisierungen können in Konflikt stehen, und ein Löschen kann in Konflikt mit einer Aktualisierung stehen.

Es gibt Frameworks wie Microsoft Sync Framework , die mit solchen Dingen umgehen .



7

Ich wette, dass Sie absolut, ohne Frage, keine referenzielle Integrität zwischen den beiden haben können. Erwarten Ihre Benutzer, dass die mobile Anwendung funktioniert, wenn die Verbindung getrennt wird?

Hierfür gibt es zwei Vorgehensweisen:

Eine Möglichkeit besteht darin, "vorläufige" Datensätze auf dem Client zu erstellen. Wenn Sie diese mit dem Server synchronisieren, weist das zentrale System die ID zu. Der Client kann den lokalen Datensatz aktualisieren, um dies widerzuspiegeln.

Zum anderen verteilen Sie die ID-Erstellung so, dass Clients (normalerweise wahrscheinlich) die ID ohne Kollisionen erstellen können.

Wechseln Sie dazu zu UUIDs - es ist ziemlich unwahrscheinlich, dass v4 kollidiert.

Andernfalls sollten Sie etwas in Betracht ziehen, das die eindeutige ID des mobilen Geräts in die Datensatz-ID einfügt. Möglicherweise handelt es sich bei Ihrer Datensatz-ID um eine ID ${imei}-${local sequence number}, bei der die IMEI die Eindeutigkeit gewährleistet und die lokale Sequenznummer lediglich eine normale sequenzielle Datenbank-ID ist.



0

Ich habe das gleiche Problem mit einem Projekt, an dem ich arbeite. In meinem Fall bestand die Lösung darin, ein zusätzliches nullwertfähiges Feld in den lokalen Tabellen mit dem Namen remote_id zu erstellen. Wenn Datensätze von der lokalen zur fernen Datenbank synchronisiert werden, wenn remote_id null ist, bedeutet dies, dass diese Zeile nie synchronisiert wurde und eine eindeutige ID zurückgeben muss, die mit der fernen Zeilen-ID übereinstimmt.

Local Table            Remote Table

_id (used locally)
remote_id ------------- id
name      ------------- name

In der Client-Anwendung verbinde ich Tabellen mit dem Feld _id, verwende das Feld "Remote-ID" aus der Ferne, um Daten abzurufen, Verknüpfungen durchzuführen usw.

Beispiel vor Ort:

Local Client Table       Local ClientType Table      Local ClientType
                         _id
                         remote_id  
_id -------------------- client_id
remote_id                client_type_id -------------- _id
                                                      remote_id
name                    name                          name

Beispiel aus der Ferne:

Remote Client Table      Remote ClientType Table      Remote ClientType
id -------------------- client_id
                        client_type_id -------------- id
name                    name                          name

Dieses Szenario ohne logischen Code würde zu Fehlern bei der Datenintegrität führen, da die Tabelle client_type möglicherweise weder in der lokalen noch in der entfernten Tabelle mit der tatsächlichen ID übereinstimmt. Daher gibt sie bei jeder Erzeugung einer remote_id ein Signal an die Clientanwendung zurück Wenn Sie aufgefordert werden, das lokale Feld _id zu aktualisieren, wird ein zuvor erstellter Trigger in sqlite ausgelöst, der die betroffenen Tabellen aktualisiert. http://www.sqlite.org/lang_createtrigger.html

1- remote_id wird auf dem Server generiert

2- gibt ein Signal an den Client zurück

3- Der Client aktualisiert das Feld _id und löst einen Trigger aus, der die lokalen Tabellen aktualisiert, die der lokalen _id beitreten

Natürlich verwende ich auch ein last_updated-Feld, um Synchronisationen zu unterstützen und doppelte Synchronisationen zu vermeiden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.