sql >> Database >  >> RDS >> Mysql

Een SQLite-clientdatabase synchroniseren met een MySQL-serverdatabase

Wel, je realiseert je dat dit een niet triviaal probleem is. Ik heb vorig jaar een bibliotheek geschreven om dit te bereiken voor een commerciële app en het duurde ongeveer zes maanden om het te krijgen waar ik blij mee was.

Afgezien van het argument voor het gebruik van poort 80 en HTTP (TCP/IP) om firewall- en ondersteuningsproblemen te voorkomen, moet u een protocol ontwerpen. Omdat mijn project erg data-intensief was, ging ik met een binair protocol (in plaats van de opgeblazen xml) dat alle gegevens aankon. Ik wilde ook dat het bidirectioneel zou zijn, zodat ik zowel gegevens kon INVOEGEN als verzoeken kon uitvoeren. Ik heb CGI/FastCGI op de server gebruikt.

Het binaire protocol dat ik heb ontworpen is vrij eenvoudig (altijd beter) en verdeelt grote overdrachten in brokken van een door de gebruiker gedefinieerde grootte (ongeveer 600k lijkt goed te zijn). Elk blok heeft een kop, gevolgd door de gegevens.

Hoewel dit protocol kan worden gebruikt voor het verzenden van alle soorten gegevens, wordt het meestal gebruikt voor gegevens in databasestijl, zoals uw vraag suggereert. Om hieraan tegemoet te komen, heb ik besloten om een ​​rijen/kolommen benadering van het ontwerp te gebruiken. De gegevens worden rij voor rij opgeslagen, wat betekent dat elk van de kolommen wordt opgeslagen voor rij één en vervolgens alle kolommen voor rij 2 ... rij n.

De indeling van gegevens met één kolom is:

' 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 is een BYTE CHAR)

Dit betekent dat elke kolom een ​​descriptor van het gegevenstype heeft. Alle datatypes kunnen worden weergegeven met:

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

Deze gegevenstypen vallen samen met de fundamentele gegevenstypen van SQLite en zijn numeriek equivalent aan de opsomming van SQL3 fundamentele gegevenstypen.

Als een veld in dit ontwerp leeg is (NULL), heeft u slechts 5 bytes nodig om het op te slaan. Als een veld bijvoorbeeld 200 bytes aan tekst bevat, heeft het slechts 205 bytes nodig om het op te slaan. Het grotere voordeel is het ontleden van de gegevens, aangezien het overslaan van kolommen kan worden gedaan zonder alle 200 bytes te lezen om een ​​afsluitend teken te vinden.

De Chunk-header zou dingen moeten bevatten zoals het aantal rijen, het aantal kolommen, het totale aantal bytes, enz. Als u DWORD's (niet-ondertekende 64-bits integers) gebruikt, dan is de theoretische limiet voor een chunk 4,2 gigabyte, wat voldoende zou moeten zijn, zelfs voor lokale netwerktransmissie.

De implementatie vereist het schrijven van SQLite/MYSQL-wrappers voor deze functionaliteit. Ik gebruik uitsluitend het BINARY-protocol, wat wat tijd kost, maar je hebt in wezen de volgende functies nodig:Client Side:SendRequest() - Verstuurt verzoek, wacht op antwoord

Serverzijde:ProcessRequest() - Ontvangt het verzoek, verwerkt het en geeft een antwoord terug

In mijn geval kan het antwoord !00MB aan gegevens of meer zijn. Ik haal de volledige dataset op uit MySQL en sla deze op schijf op de server op. Vervolgens retourneer ik een leeg stuk dat de gegevensset-statistieken bevat. De client vraagt ​​de dataset vervolgens één voor één op in brokken van 600k. Als de verbinding wegvalt, gaat hij verder waar hij was gebleven.

Ten slotte bestond de dataset voornamelijk uit tekst (namen, adressen, enz.) dus rijp voor compressie. Beveiliging was in dit geval een zeer groot probleem, dus codering was essentieel. Dit wordt een beetje ingewikkelder om te implementeren, maar in feite comprimeer je het hele stuk, pad tot een lengte die een veelvoud is van de blokcijfers BLOCKSIZE en versleutelt het.

Tijdens dit alles schrijf ik een zeer snelle stringbuilderklasse, een implementatie van AES-codering in ASM en een volledige FastCGI-bibliotheek (www.coastrd.com)

Dus zoals ik al zei, niet triviaal. Ik zal deze bibliotheek binnenkort beschikbaar stellen. Als je het wilt bekijken, stuur me dan een e-mail.

Zodra u de communicatie hebt geschreven, kunt u beginnen met het ontwerpen van de synchronisatie. Ik zou ofwel een hash gebruiken voor elke record, of een eenvoudige booleaanse vlag. Als er iets verandert op de server, stuur dan gewoon het hele record en overschrijf het aan de clientzijde (ervan uitgaande dat u probeert de clients gesynchroniseerd te houden...)

Als je er zelf een schrijft, post dan hier over je ervaringen!

ps. Overweeg de titel te wijzigen om deze zoekvriendelijker te maken. Misschien zoiets als:

"Synchroniseren van een SQLite-clientdatabase met een MySQL-serverdatabase"



  1. MySQL:dateert van vóór 1970

  2. Gegevens ontleden en vergelijken met Coldfusion &MySQL

  3. Een 32-bits applicatie verbinden met jBASE

  4. PostgreSQL-afstemmingsinterval tussen start- en eindtijd tegen tijdstempel