Mysql
 sql >> Database >  >> RDS >> Mysql

Sincronizzazione di un database client SQLite con un database server MySQL

Bene, ti rendi conto che questo è un problema non banale. Ho scritto una libreria per ottenere questo risultato per un'app commerciale l'anno scorso e ci sono voluti circa 6 mesi per portarla dove ero soddisfatto.

Lasciando da parte l'argomento per l'utilizzo della porta 80 e HTTP (TCP/IP) per evitare problemi di firewall e supporto, è necessario progettare un protocollo. Poiché il mio progetto richiedeva molto dati, sono andato con un protocollo binario (piuttosto che l'xml gonfio) in grado di gestire qualsiasi dato. Volevo anche che fosse bidirezionale in modo da poter INSERIRE dati ed eseguire richieste. Ho usato CGI/FastCGI sul server.

Il protocollo binario che ho progettato è abbastanza semplice (sempre migliore) e suddivide i trasferimenti di grandi dimensioni in blocchi di una dimensione definita dall'utente (circa 600k sembra essere buono). Ogni blocco ha un'intestazione seguita dai dati.

Sebbene questo protocollo possa essere utilizzato per trasmettere qualsiasi tipo di dati, in genere viene utilizzato per dati in stile database come suggerisce la tua domanda. Per adattarsi a questo, ho deciso di utilizzare un approccio di righe/colonne al design. I dati vengono memorizzati una riga alla volta, il che significa che ciascuna delle colonne viene memorizzata per la riga uno, quindi tutte le colonne per la riga 2 ... riga n.

Il formato dei dati di una singola colonna è:

' Col1Type          1Bytes - BYTE     ' Data Type (REMSQL_TEXT etc)                
' Col1Len           4Bytes - DWORD    ' Length in bytes the Column Data                            - up to 4.2GB
' Col1Data          nBytes - BYTE     ' String data  

(in C, un BYTE è CHAR)

Ciò significa che ogni colonna ha un descrittore del tipo di dati. Tutti i tipi di dati possono essere rappresentati con:

REMSQL_NONE = 0    ' DataType undefined
REMSQL_QUAD = 1    ' 64-bit signed integer                
REMSQL_DBLE = 2    ' 64-bit IEEE floating point number
REMSQL_TEXT = 3    ' STRING - (CHAR) string of Ascii Bytes                                     
REMSQL_BLOB = 4    ' BLOB - (CHAR) string of Binary Bytes                                       
REMSQL_NULL = 5    ' NULL - Empty Column

Questi tipi di dati coincidono con i tipi di dati fondamentali di SQLite e sono numericamente equivalenti all'enumerazione dei tipi di dati fondamentali di SQL3.

In questo progetto, se un campo è vuoto (NULL), sono stati necessari solo 5 byte per memorizzarlo. Se ad esempio un campo ha 200 byte di testo, sono necessari solo 205 byte per memorizzarlo. Il vantaggio maggiore consiste nell'analisi dei dati poiché è possibile saltare le colonne senza leggere tutti i 200 byte per trovare un carattere di terminazione.

L'intestazione Chunk dovrebbe contenere cose come numero di righe, numero di colonne, byte totali, ecc. Se usi DWORD (interi a 64 bit senza segno), il limite teorico per un blocco è 4,2 gigs che dovrebbe essere sufficiente anche per la trasmissione di rete locale.

L'implementazione richiede la scrittura di wrapper SQLite/MYSQL per questa funzionalità. Uso esclusivamente il protocollo BINARY, che richiede un po' di tempo, ma essenzialmente sono necessarie le seguenti funzioni:Lato client:SendRequest() - Invia richiesta, attende risposta

Lato server:ProcessRequest() - Riceve la richiesta, la elabora e restituisce la risposta

Nel mio caso, la risposta può essere !00 MB di dati o più. Recupero l'intero set di dati da MySQL e lo salvo su disco sul server. Quindi restituisco un blocco vuoto che contiene le metriche del set di dati. Il client richiede quindi il set di dati in blocchi di 600.000, uno per uno. Se la connessione viene persa, riprende da dove era stata interrotta.

Infine, il set di dati era principalmente di testo (nomi, indirizzi, ecc.) Così maturo per la compressione. La sicurezza era un grosso problema in questo caso, quindi la crittografia era essenziale. Questo diventa un po' più complicato da implementare, ma fondamentalmente si comprime l'intero blocco, si riempie a una lunghezza che è un multiplo delle cifre a blocchi BLOCKSIZE e lo si crittografa.

Nel processo di tutto ciò scrivo una classe di creazione di stringhe molto veloce, un'implementazione della crittografia AES in ASM e un'intera libreria FastCGI (www.coastrd.com)

Quindi, come ho detto, non banale. Presto metterò a disposizione questa libreria. Se vuoi dare un'occhiata, mandami un'e-mail.

Una volta che hai scritto la comunicazione, puoi iniziare a progettare la sincronizzazione. Userei un hash per ogni record o un semplice flag booleano. Se qualcosa cambia sul server, invia l'intero record e sovrascrivilo sul lato client (supponendo che tu stia cercando di mantenere sincronizzati i client...)

Se scrivi la tua, per favore posta qui di nuovo la tua esperienza!

PS. Prendi in considerazione la possibilità di modificare il titolo in modo che sia più intuitivo per la ricerca. Forse qualcosa del tipo:

"Sincronizzazione di un database client SQLite con un database server MySQL"