Mantenimento dell'integrità referenziale tra un client mobile e un server

19

Quindi ho un sistema relativamente semplice. Un client mobile crea record in un database SQLite che vorrei sincronizzare con un server SQL remoto (condiviso con altri client mobili) . Quindi, quando creo un nuovo record nella tabella sqlite del telefono, spingo quella modifica al mio servizio remoto attraverso un'API RESTful. Il problema che sto riscontrando è come faccio a ordinare le chiavi primarie in modo che non ci siano collisioni nei dati (cioè un record nel telefono ha la stessa chiave primaria di un record completamente diverso su il server). Qual è la solita "procedura migliore per fare riferimento al record sul client e per fare riferimento allo stesso record sul server?

    
posta JoeCortopassi 31.01.2012 - 20:44
fonte

4 risposte

20

La pratica normale è strutturare il tuo database con le chiavi uniqueidentifier (a volte chiamate UUID o GUID). Puoi crearli in due posti senza timori realistici di collisione.

Successivamente, l'app per dispositivi mobili deve sincronizzare le tabelle "fact" dal server prima di poter creare nuove righe. Quando crei nuove righe, lo fai localmente e quando esegui di nuovo la sincronizzazione, vengono aggiunte nuove righe al server. Puoi fare lo stesso con aggiornamenti ed eliminazioni.

Per tenere traccia degli inserti è necessario un timestamp creato sulle tue righe. Per tenere traccia degli aggiornamenti devi tenere traccia di un timestamp LastUpdate sulle tue righe. Per tracciare le eliminazioni è necessaria una tabella tombstone.

Notare che quando si esegue una sincronizzazione, è necessario controllare l'intervallo di tempo tra il server e il dispositivo mobile e occorre disporre di un metodo per risolvere i conflitti. Gli inserti non sono un grosso problema (non dovrebbero essere in conflitto), ma gli aggiornamenti potrebbero entrare in conflitto e un'eliminazione potrebbe entrare in conflitto con un aggiornamento.

Esistono framework per gestire questo tipo di cose, come Microsoft Sync Framework .

    
risposta data 31.01.2012 - 21:08
fonte
7

Scommetto che tu assolutamente, senza dubbio non puoi avere integrità referenziale tra i due. In particolare, i tuoi utenti si aspettano che l'applicazione mobile funzioni quando è disconnessa?

Ci sono due pratiche per questo:

Uno è quello di creare record "provvisori" sul client, e poi quando li sincronizzi con il server, il sistema centrale assegna l'ID. Il client può aggiornare il record locale per riflettere quello.

L'altro è che si distribuisce la creazione di ID in un modo che (normalmente in modo probabilistico) consente ai clienti di creare l'ID senza collisioni.

Per questo, vai agli UUID: è molto improbabile che v4 collidano.

Altrimenti, considera qualcosa che collochi l'ID univoco del dispositivo mobile nell'ID del record. Pertanto, l'ID del record potrebbe essere ${imei}-${local sequence number} o qualcosa, in cui l'IMEI garantisce l'unicità e il numero di sequenza locale è solo un normale ID di database sequenziale.

    
risposta data 31.01.2012 - 20:51
fonte
2

Oltre alla risposta di Daniel Pittman , una possibilità sarebbe che il server assegni a ciascun cliente un client unico ID e rendere l'ID cliente una parte della chiave primaria.

    
risposta data 31.01.2012 - 20:55
fonte
0

Ho lo stesso problema con un progetto su cui sto lavorando, la soluzione nel mio caso era quella di creare un campo nullo extra nelle tabelle locali chiamate remote_id. Quando sincronizzi i record dal database locale a quello remoto se remote_id è nullo, significa che questa riga non è mai stata sincronizzata e deve restituire un ID univoco che corrisponde all'id della riga remota.

Local Table            Remote Table

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

Nell'applicazione client collego le tabelle tramite il campo _id, in remoto utilizzo il campo id remoto per recuperare dati, fare join, ecc.

esempio locale:

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

esempio da remoto:

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

Questo scenario, e senza alcuna logica nel codice, causerebbe errori di integrità dei dati, poiché la tabella client_type potrebbe non corrispondere all'ID reale nelle tabelle locali o remote, quindi ogni volta che viene generato un remote_id, restituisce un segnale a l'applicazione client che chiede di aggiornare il campo _id locale, attiva un trigger precedentemente creato in sqlite aggiornando le tabelle interessate. link

1- remote_id è generato nel server

2- restituisce un segnale al client

3- client aggiorna il suo campo _id e attiva un trigger che aggiorna le tabelle locali che uniscono _id

locale

Naturalmente utilizzo anche un campo last_updated per aiutare le sincronizzazioni ed evitare sincronizzazioni duplicate.

    
risposta data 18.05.2014 - 17:17
fonte

Leggi altre domande sui tag