Sincronización de una base de datos de cliente SQLite con una base de datos de servidor MySQL

He creado una aplicación en xcode con sqlite. Quiero crear un botón llamado sincronización para sincronizar con mi base de datos mysql en mi servidor. ¿Alguna sugerencia sobre el proceso de sincronización? Por favor hagamelo saber.

Use un servicio web en el servidor para devolver tanto un número de versión de esquema como un último sello de fecha y hora actualizado. Si el cliente está desactualizado, realiza una segunda llamada para obtener el esquema actualizado y / o nuevos datos.

Bien, te das cuenta de que este es un problema no trivial. El año pasado escribí una biblioteca para lograr esto para una aplicación comercial y tardé aproximadamente 6 meses en llegar a donde estaba contento.

Dejando de lado el argumento para usar el puerto 80 y HTTP (TCP / IP) para evitar problemas de firewall y soporte, debe diseñar un protocolo. Como mi proyecto era muy dependiente de los datos, opté por un protocolo binario (en lugar del xml inflado) que podía manejar cualquier dato. También quería que fuera bidireccional para poder INSERTAR datos y ejecutar solicitudes. Usé CGI / FastCGI en el servidor.

El protocolo binario que diseñé es bastante simple (siempre mejor) y rompe transferencias grandes en trozos de un tamaño definido por el usuario (aproximadamente 600k parece ser bueno). Cada fragmento tiene un encabezado seguido de los datos.

Aunque este protocolo se puede usar para transmitir cualquier tipo de datos, por lo general se usa para datos de estilo de base de datos como sugiere su pregunta. Para acomodar esto, decidí usar un enfoque filas / columnas para el diseño. Los datos se almacenan una fila a la vez, es decir, cada una de las columnas se almacena para la fila uno, luego todas las columnas para la fila 2 … fila n.

El formato de los datos de una sola columna es:

' 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 es CHAR)

Esto significa que cada columna tiene un descriptor de tipo de datos. Todos los tipos de datos se pueden representar con:

 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 

Estos tipos de datos coinciden con los tipos de datos fundamentales de SQLite y son numéricamente equivalentes a la enumeración de tipos de datos fundamentales de SQL3.

En este diseño, si un campo está vacío (NULO), entonces solo ha tomado 5 bytes para almacenarlo. Si un campo tiene 200 bytes de texto, por ejemplo, solo se necesitan 205 bytes para almacenarlo. El mayor beneficio se obtiene al analizar los datos, ya que se pueden omitir las columnas sin leer los 200 bytes para encontrar algún carácter de terminación.

El encabezado de Chunk debe contener cosas como, número de filas, número de columnas, bytes totales, etc. Si usa DWORD (enteros de 64 bits sin signo), el límite teórico para un fragmento es de 4.2gigs, que debería ser suficiente incluso para la transmisión de la red local.

La implementación requiere escribir contenedores SQLite / MYSQL para esta funcionalidad. Uso el protocolo BINARY exclusivamente, lo que lleva un poco de tiempo, pero básicamente necesitas las siguientes funciones: Lado del cliente: SendRequest () – Envía la solicitud, espera la respuesta

Lado del servidor: ProcessRequest (): recibe la solicitud, la procesa y devuelve la respuesta

En mi caso, la respuesta puede ser! 00MB de datos o más. Recupero todo el conjunto de datos de MySQL y lo guardo en el disco del servidor. Luego devuelvo un fragmento vacío que contiene las métricas del conjunto de datos. El cliente luego solicita el conjunto de datos en fragmentos de 600k, uno por uno. Si la conexión se pierde, simplemente continúa donde lo dejó.

Finalmente, el conjunto de datos era principalmente texto (direcciones de nombres, etc.) tan maduro para la compresión. La seguridad era un tema muy importante en este caso, por lo que el cifrado era esencial. Esto se vuelve un poco más complicado de implementar, pero básicamente comprimes todo el fragmento, el pad a una longitud que es un múltiplo de las cifras cifradas BLOCKSIZE y lo encriptas.

En el proceso de todo esto, escribo una clase de creador de cadenas muy rápido, una implementación de encriptación AES en ASM y una biblioteca completa de FastCGI (www.coastrd.com)

Entonces, como dije, no es trivial. Estaré disponible esta biblioteca pronto. Si quieres verificarlo, envíame un correo electrónico.

Una vez que haya escrito la comunicación, puede comenzar a diseñar la sincronización. Yo usaría un hash para cada registro, o un simple indicador booleano. Si algo cambia en el servidor, simplemente envíe el registro completo y sobrescríbalo en el lado del cliente (suponiendo que esté tratando de mantener a los clientes sincronizados …)

Si escribes el tuyo, ¡vuelve a publicar aquí tu experiencia!

PD. Considere cambiar el título para que sea más amigable para la búsqueda. Quizás algo así como:

“Sincronización de una base de datos de cliente SQLite con una base de datos de servidor MySQL”

Creo que está diciendo que tiene un servidor MySql ejecutándose en una computadora y que está ejecutando una aplicación con una instancia sqlite y desea actualizar el servidor sqlite si hay nuevos datos en el servidor MySQL.

Lo haría de esta manera

1) Asegúrese de que tanto la tabla de su computadora como la de la aplicación tengan la misma estructura. Incluir un último campo actualizado

2) Para verificar quién está más actualizado, obtenga la última fila con su clave única y luego compare el campo actualizado.

3) Cuando el campo más actualizado pertenece al servidor, entienda cuántas filas son diferentes y comience a copiarlas en un ciclo do … while () o como prefiera.

Si implementa este código tanto en el servidor como en el cliente, entonces pueden actualizarse entre sí o si solo desea actualizar el cliente.

Los detalles dependen del idioma que desea utilizar y la cantidad de tiempo que desea poner en desarrollo.

Unas cuantas preguntas:

  • ¿Está intentando una sincronización bidireccional o simplemente está sacando actualizaciones del servidor?
  • ¿Qué operaciones de actualización son aceptables? Insertar / Actualizar / Eliminar? En las bases de datos replicadas, las eliminaciones generalmente se evitan.

Si solo necesita extraer insertos / actualizaciones del servidor, podría crear un script PHP, que devolvería las sentencias SQLite para ejecutar. La secuencia de comandos php tomaría un parámetro de la última secuencia / hora de actualización del cliente.

Si planeas hacer una sincronización bidireccional, entonces debes pensar en fusiones y resolución de conflictos. Para ambos sentidos, es mejor que cada lado tenga una cola de transacciones. Simplemente registre cada instrucción CRUD ejecutada contra la base de datos. Al sincronizar, aplique estas declaraciones y luego trunque la cola.

SQuirreL SQL (en Java utilizando Hibernate) tiene un complemento DBCopy. Podría ser posible crear una copia de la base de datos usando eso. No lo he intentado, pero esa es la primera dirección que tomaría.

entropyDb tiene una función de replicación automática que podría manejar esto