Mysql
 sql >> Base de données >  >> RDS >> Mysql

Synchroniser une base de données client SQLite avec une base de données serveur MySQL

Eh bien, vous vous rendez compte que c'est un problème non trivial. J'ai écrit une bibliothèque pour accomplir cela pour une application commerciale l'année dernière et il a fallu environ 6 mois pour l'amener là où j'en étais satisfait.

Laissant de côté l'argument de l'utilisation du port 80 et HTTP (TCP/IP) pour éviter les problèmes de pare-feu et de support, vous devez concevoir un protocole. Étant donné que mon projet était très gourmand en données, j'ai opté pour un protocole binaire (plutôt que le xml gonflé) qui pouvait gérer toutes les données. Je voulais aussi qu'il soit bidirectionnel pour pouvoir INSÉRER des données et exécuter des requêtes. J'ai utilisé CGI/FastCGI sur le serveur.

Le protocole binaire que j'ai conçu est assez simple (toujours meilleur) et divise les gros transferts en morceaux d'une taille définie par l'utilisateur (environ 600k semble être bon). Chaque morceau a un en-tête suivi des données.

Bien que ce protocole puisse être utilisé pour transmettre tout type de données, il est généralement utilisé pour les données de style base de données, comme le suggère votre question. Pour répondre à cela, j'ai décidé d'utiliser une approche lignes/colonnes pour la conception. Les données sont stockées une ligne à la fois, ce qui signifie que chacune des colonnes est stockée pour la ligne 1, puis toutes les colonnes pour la ligne 2 ... ligne n.

Le format des données d'une seule colonne est :

' 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  

(en C, un BYTE est CHAR)

Cela signifie que chaque colonne a un descripteur de type de données. Tous les types de données peuvent être représentés par :

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

Ces types de données coïncident avec les types de données fondamentaux SQLite et sont numériquement équivalents à l'énumération des types de données fondamentaux SQL3.

Dans cette conception, si un champ est vide (NULL), vous n'avez pris que 5 octets pour le stocker. Si un champ a 200 octets de texte par exemple, il ne faut que 205 octets pour le stocker. Le plus grand avantage réside dans l'analyse des données, car il est possible de sauter des colonnes sans lire les 200 octets pour trouver un caractère de fin.

L'en-tête Chunk doit contenir des éléments tels que le nombre de lignes, le nombre de colonnes, le nombre total d'octets, etc. Si vous utilisez des DWORD (entiers 64 bits non signés), la limite théorique pour un bloc est de 4,2 gigaoctets, ce qui devrait suffire même pour la transmission sur le réseau local.

L'implémentation nécessite l'écriture de wrappers SQLite/MYSQL pour cette fonctionnalité. J'utilise exclusivement le protocole BINARY, ce qui prend un peu de temps, mais vous avez essentiellement besoin des fonctions suivantes :Côté client :SendRequest() - Envoie la requête, attend la réponse

Côté serveur :ProcessRequest() - Reçoit la requête, la traite et renvoie la réponse

Dans mon cas, la réponse peut être ! 00 Mo de données ou plus. Je récupère l'ensemble des données de MySQL et l'enregistre sur le disque du serveur. Ensuite, je renvoie un morceau vide contenant les métriques de l'ensemble de données. Le client demande ensuite l'ensemble de données en morceaux de 600k, un par un. Si la connexion est perdue, elle reprend là où elle s'était arrêtée.

Enfin, l'ensemble de données était principalement composé de texte (noms, adresses, etc.) si mûr pour la compression. La sécurité était un très gros problème dans ce cas, le cryptage était donc essentiel. Cela devient un peu plus compliqué à mettre en œuvre, mais en gros, vous compressez le morceau entier, remplissez à une longueur qui est un multiple des chiffrements de bloc BLOCKSIZE et chiffrez-le.

Au cours de tout cela, j'écris une classe de création de chaînes très rapide, une implémentation du cryptage AES dans ASM et une bibliothèque FastCGI complète (www.coastrd.com)

Donc comme je l'ai dit, non trivial. Je mettrai cette bibliothèque à disposition prochainement. Si vous voulez le vérifier, écrivez-moi.

Une fois que vous avez rédigé la communication, vous pouvez commencer à concevoir la synchronisation. J'utiliserais soit un hachage pour chaque enregistrement, soit un simple drapeau booléen. Si quelque chose change sur le serveur, envoyez simplement l'intégralité de l'enregistrement et écrasez-le côté client (en supposant que vous essayez de synchroniser les clients...)

Si vous écrivez le vôtre, veuillez publier ici votre expérience !

PS. Envisagez de modifier le titre pour qu'il soit plus convivial pour la recherche. Peut-être quelque chose comme :

"Synchronisation d'une base de données client SQLite avec une base de données serveur MySQL"