Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Synchronizacja bazy danych klienta SQLite z bazą danych serwera MySQL

Zdajesz sobie sprawę, że nie jest to trywialny problem. Napisałem bibliotekę, aby to zrobić dla komercyjnej aplikacji w zeszłym roku i zajęło około 6 miesięcy, zanim dotarłem do miejsca, w którym byłem z niego zadowolony.

Pomijając argument za używaniem portu 80 i HTTP (TCP/IP), aby uniknąć problemów z zaporą sieciową i obsługą, musisz zaprojektować protokół. Ponieważ mój projekt wymagał dużej ilości danych, wybrałem protokół binarny (zamiast nadętego xml), który mógł obsłużyć dowolne dane. Chciałem również, aby był dwukierunkowy, abym mógł WSTAWIĆ dane, a także wykonywać żądania. Użyłem CGI/FastCGI na serwerze.

Zaprojektowany przeze mnie protokół binarny jest dość prosty (zawsze lepszy) i dzieli duże transfery na porcje o rozmiarze określonym przez użytkownika (około 600k wydaje się być dobre). Każdy fragment ma nagłówek, po którym następują dane.

Chociaż ten protokół może być używany do przesyłania dowolnego rodzaju danych, zazwyczaj jest używany do danych w stylu bazy danych, jak sugeruje twoje pytanie. Aby to pogodzić, zdecydowałem się zastosować w projekcie podejście wierszy/kolumn. Dane są przechowywane w jednym wierszu na raz, co oznacza, że ​​każda z kolumn jest przechowywana w wierszu pierwszym, a następnie wszystkie kolumny w wierszu 2 ... wiersz n.

Format danych w jednej kolumnie to:

' 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  

(w C, BYTE to CHAR)

Oznacza to, że każda kolumna ma deskryptor typu danych. Wszystkie typy danych mogą być reprezentowane przez:

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

Te typy danych pokrywają się z podstawowymi typami danych SQLite i są numerycznie równoważne wyliczeniu podstawowych typów danych SQL3.

W tym projekcie, jeśli pole jest puste (NULL), to zajęło Ci tylko 5 bajtów, aby je przechować. Jeśli pole ma na przykład 200 bajtów tekstu, zapisanie go zajmuje tylko 205 bajtów. Większą korzyścią jest parsowanie danych, ponieważ pomijanie kolumn można wykonać bez czytania wszystkich 200 bajtów w celu znalezienia jakiegoś znaku kończącego.

Nagłówek Chunk powinien zawierać takie rzeczy, jak liczba wierszy, liczba kolumn, całkowita liczba bajtów itp. Jeśli używasz DWORDs (64-bitowe liczby całkowite bez znaku), to teoretyczny limit dla fragmentu wynosi 4,2gigs, co powinno wystarczyć nawet do transmisji w sieci lokalnej.

Implementacja wymaga napisania wrapperów SQLite/MYSQL dla tej funkcjonalności. Używam wyłącznie protokołu BINARY, co zajmuje trochę czasu, ale zasadniczo potrzebujesz następujących funkcji:Strona klienta:SendRequest() - Wysyła żądanie, czeka na odpowiedź

Po stronie serwera:ProcessRequest() — odbiera żądanie, przetwarza je i zwraca odpowiedź

W moim przypadku odpowiedzią może być !00MB danych lub więcej. Pobieram cały zestaw danych z MySQL i zapisuję go na dysku na serwerze. Następnie zwracam pustą porcję zawierającą metryki zestawu danych. Klient następnie żąda zestawu danych w kawałkach po 600 tys., jeden po drugim. Jeśli połączenie zostanie utracone, po prostu wznowi w miejscu, w którym zostało przerwane.

Wreszcie zestaw danych składał się głównie z tekstu (nazwy, adresy itp.), więc był gotowy do kompresji. Bezpieczeństwo było w tym przypadku bardzo dużym problemem, więc szyfrowanie było niezbędne. To trochę bardziej skomplikowane do zaimplementowania, ale w zasadzie kompresujesz cały fragment, dopełniasz do długości będącej wielokrotnością szyfrów blokowych ROZMIAR BLOKU i szyfrujesz.

W trakcie tego wszystkiego piszę bardzo szybką klasę konstruktora ciągów, implementację szyfrowania AES w ASM i całą bibliotekę FastCGI (www.coastrd.com)

Więc jak powiedziałem, nietrywialne. Wkrótce udostępnię tę bibliotekę. Jeśli chcesz to sprawdzić, napisz do mnie.

Po napisaniu komunikatu możesz zacząć projektować synchronizację. Dla każdego rekordu użyłbym skrótu lub prostej flagi logicznej. Jeśli coś się zmieni na serwerze, po prostu wyślij cały rekord i nadpisz go po stronie klienta (zakładając, że próbujesz zsynchronizować klientów...)

Jeśli napiszesz własne, opublikuj tutaj swoje wrażenia!

PS. Rozważ zmianę tytułu, aby był bardziej przyjazny dla wyszukiwania. Może coś takiego:

"Synchronizacja bazy danych klienta SQLite z bazą danych serwera MySQL"



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL:Zwracanie najczęstszej wartości dla każdej osoby

  2. Emuluj klauzulę LIMIT MySQL w Microsoft SQL Server 2000

  3. Mysql - Zmienna OUT procedury składowanej zwraca wartość null

  4. Implementacja algorytmu ray-castingu w MySQL?

  5. Łączenie dwóch tabel o różnej liczbie kolumn