sql >> Databasteknik >  >> RDS >> Mysql

Synkronisera en SQLite-klientdatabas med en MySQL-serverdatabas

Du inser att detta är ett icke trivialt problem. Jag skrev ett bibliotek för att åstadkomma detta för en kommersiell app förra året och det tog ungefär 6 månader att få den dit jag var nöjd med den.

Bortsett från argumentet för att använda port 80 och HTTP (TCP/IP) för att undvika brandväggs- och supportproblem, måste du designa ett protokoll. Eftersom mitt projekt var mycket dataintensivt valde jag ett binärt protokoll (snarare än den uppsvällda xml) som kunde hantera alla data. Jag ville också att den skulle vara dubbelriktad så att jag kunde INFOGA data samt utföra förfrågningar. Jag använde CGI/FastCGI på servern.

Det binära protokollet jag designade är ganska enkelt (alltid bättre) och delar upp stora överföringar i bitar av en användardefinierad storlek (cirka 600k verkar vara bra). Varje del har en rubrik följt av data.

Även om detta protokoll kan användas för att överföra alla typer av data, används det vanligtvis för databasformat som din fråga antyder. För att tillgodose detta, bestämde jag mig för att använda ett rader/kolumner tillvägagångssätt för designen. Data lagras en rad i taget, vilket innebär att var och en av kolumnerna lagras för rad ett, sedan alla kolumner för rad 2 ... rad n.

Formatet för en enskild kolumndata är:

' 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 är en BYTE CHAR)

Detta innebär att varje kolumn har en datatypsbeskrivning. Alla datatyper kan representeras 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

Dessa datatyper sammanfaller med SQLite grundläggande datatyper och är numeriskt ekvivalenta med SQL3 Fundamental Datatypes uppräkning.

I denna design, om ett fält är tomt (NULL) har du bara tagit 5 ​​byte för att lagra det. Om ett fält har 200 byte text till exempel, tar det bara 205 byte att lagra det. Den större fördelen är att analysera data eftersom det går att hoppa över kolumner utan att läsa igenom alla 200 byte för att hitta något avslutande tecken.

Chunk-rubriken bör innehålla saker som antal rader, antal kolumner, totala byte etc etc. Om du använder DWORDs (osignerade 64-bitars heltal) så är den teoretiska gränsen för en chunk 4.2gig vilket borde räcka även för lokala nätverksöverföringar.

Implementeringen kräver att man skriver SQLite/MYSQL-omslag för denna funktionalitet. Jag använder uteslutande det BINÄRA protokollet, vilket tar lite tid, men du behöver i huvudsak följande funktioner:Klientsidan:SendRequest() - Skickar förfrågan, väntar på svar

Serversidan:ProcessRequest() - tar emot förfrågan, bearbetar den och returnerar svar

I mitt fall kan svaret vara !00MB data eller mer. Jag hämtar hela datamängden från MySQL och sparar den på disken på servern. Sedan returnerar jag en tom del som innehåller datamängden. Klienten begär sedan datamängden i bitar om 600k, en efter en. Om anslutningen bryts fortsätter den där den slutade.

Slutligen var datamängden mestadels text (namn adresser etc) så mogen för komprimering. Säkerhet var ett mycket stort problem i det här fallet så kryptering var viktigt. Detta blir lite mer komplicerat att implementera, men i princip komprimerar du hela biten, pad till en längd som är en multipel av blockchiffrorna BLOCKSIZE och krypterar den.

I processen med allt detta skriver jag en mycket snabb strängbyggarklass, en implementering av AES-kryptering i ASM och ett helt FastCGI-bibliotek (www.coastrd.com)

Så som sagt, icke trivialt. Jag kommer att göra det här biblioteket tillgängligt snart. Om du vill kolla in det, maila mig.

När du har skrivit meddelandet kan du börja designa synkroniseringen. Jag skulle antingen använda en hash för varje post, eller en enkel boolesk flagga. Om något ändras på servern, skicka bara hela posten och skriv över den på klientsidan (förutsatt att du försöker hålla klienterna synkroniserade...)

Om du skriver din egen, vänligen posta tillbaka här om din upplevelse!

PS. Överväg att ändra titeln för att vara mer sökvänlig. Kanske något i stil med:

"Synkronisera en SQLite-klientdatabas med en MySQL-serverdatabas"



  1. SQL Server:DELETE vs TRUNCATE

  2. Installera SQL Server Agent Extension på Azure Data Studio

  3. ASP.Net / MySQL :Översätter innehåll till flera språk

  4. Bör varje användartabell ha ett klusterindex?