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

Synkronisering af en SQLite-klientdatabase med en MySQL-serverdatabase

Nå, du ved, at dette er et ikke-trivielt problem. Jeg skrev et bibliotek for at opnå dette for en kommerciel app sidste år, og det tog omkring 6 måneder at få den til, hvor jeg var tilfreds med den.

Hvis man ser bort fra argumentet for at bruge port 80 og HTTP (TCP/IP) for at undgå firewall- og supportproblemer, skal du designe en protokol. Da mit projekt var meget datakrævende, gik jeg med en binær protokol (i stedet for den oppustede xml), der kunne håndtere alle data. Jeg ønskede også, at det skulle være tovejs, så jeg kunne INDSÆTTE data samt udføre anmodninger. Jeg brugte CGI/FastCGI på serveren.

Den binære protokol, jeg har designet, er ret enkel (altid bedre) og deler store overførsler i bidder af en brugerdefineret størrelse (ca. 600k ser ud til at være godt). Hver del har en overskrift efterfulgt af dataene.

Selvom denne protokol kan bruges til at overføre enhver form for data, bruges den typisk til databasestildata, som dit spørgsmål antyder. For at imødekomme dette besluttede jeg at bruge en rækker/søjler tilgang til designet. Dataene gemmes en række ad gangen, hvilket betyder, at hver af kolonnerne gemmes for række et, derefter alle kolonnerne for række 2 ... række n.

Formatet for en enkelt kolonnes data er:

' 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  

(i C er en BYTE CHAR)

Det betyder, at hver kolonne har en datatypebeskrivelse. Alle datatyper kan repræsenteres med:

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

Disse datatyper falder sammen med SQLite grundlæggende datatyper og svarer numerisk til SQL3 Fundamental Datatypes opregning.

I dette design, hvis et felt er tomt (NULL), har du kun brugt 5 bytes for at gemme det. Hvis et felt f.eks. har 200 bytes tekst, tager det kun 205 bytes at gemme det. Den største fordel er at parse dataene, da det kan ske at springe kolonner over uden at læse alle 200 bytes igennem for at finde et afsluttende tegn.

Chunk-headeren skal indeholde ting som antal rækker, antal kolonner, totale bytes osv. osv. Hvis du bruger DWORDs (usigned 64bit heltal), så er den teoretiske grænse for en chunk 4.2gig, hvilket burde være nok selv for lokal netværkstransmission.

Implementeringen kræver skrivning af SQLite/MYSQL wrappers til denne funktionalitet. Jeg bruger udelukkende BINÆR-protokollen, hvilket tager lidt tid, men du har grundlæggende brug for følgende funktioner:Klientside:SendRequest() - Sender anmodning, venter på svar

Serverside:ProcessRequest() - Modtager anmodning, behandler den og returnerer svar

I mit tilfælde kan svaret være !00 MB data eller mere. Jeg henter hele datasættet fra MySQL og gemmer det på disken på serveren. Så returnerer jeg en tom del, der indeholder datasættets metrics. Klienten anmoder derefter om datasættet i bidder af 600k, én efter én. Hvis forbindelsen afbrydes, fortsætter den bare, hvor den slap.

Endelig var datasættet for det meste tekst (navne adresser osv.), så modent til komprimering. Sikkerhed var et meget stort problem i dette tilfælde, så kryptering var afgørende. Dette bliver lidt mere kompliceret at implementere, men dybest set komprimerer du hele klumpen, pad til en længde, der er et multiplum af blokcifrene BLOCKSIZE og krypterer det.

I processen med alt dette skriver jeg en meget hurtig strengbuilderklasse, en implementering af AES-kryptering i ASM og et helt FastCGI-bibliotek (www.coastrd.com)

Så som sagt ikke trivielt. Jeg vil snart gøre dette bibliotek tilgængeligt. Hvis du vil tjekke det ud, så send mig en e-mail.

Når du har skrevet kommunikationen, kan du begynde at designe synkroniseringen. Jeg ville enten bruge en hash for hver post eller et simpelt boolesk flag. Hvis noget ændrer sig på serveren, skal du bare sende hele posten og overskrive den på klientsiden (forudsat at du forsøger at holde klienterne synkroniseret...)

Hvis du skriver din egen, bedes du skrive tilbage her om din oplevelse!

PS. Overvej at ændre titlen for at være mere søgevenlig. Måske noget som:

"Synkronisering af en SQLite-klientdatabase med en MySQL-serverdatabase"



  1. sqlite get felt med mere end 2 MB

  2. Beregn decil i MySQL baseret på totaler

  3. Oracle - Sådan opretter du en materialiseret visning med HURTIG OPDATERING og JOINS

  4. Sender et array til mysql