Entonces tengo un sistema relativamente simple. Un cliente móvil crea registros en una base de datos sqlite que me gustaría sincronizar con un servidor SQL remoto (que se comparte con otros clientes móviles) . Entonces, cuando creo un nuevo registro en la tabla sqlite del teléfono, entonces empujo ese cambio a mi servicio remoto a través de una API RESTful. El problema que tengo es cómo ordenar las claves primarias para que no haya colisiones en los datos (es decir, un registro en el teléfono tiene la misma clave primaria que un registro completamente diferente en el servidor). ¿Cuál es la "práctica recomendada habitual para hacer referencia al registro en el cliente y para hacer referencia al mismo registro en el servidor?
sql
web-services
JoeCortopassi
fuente
fuente
Respuestas:
La práctica normal es estructurar su base de datos con
uniqueidentifier
claves (a veces llamadas UUID o GUID). Puede crearlos en dos lugares sin temor realista de colisión.A continuación, su aplicación móvil debe sincronizar tablas de "hechos" del servidor antes de que pueda crear nuevas filas. Cuando crea nuevas filas, lo hace localmente, y cuando vuelve a sincronizar, se agregan nuevas filas al servidor. Puede hacer lo mismo con las actualizaciones y eliminaciones también.
Para realizar un seguimiento de las inserciones, necesita una marca de tiempo creada en sus filas. Para rastrear las actualizaciones, debe rastrear una marca de tiempo LastUpdate en sus filas. Para realizar un seguimiento de las eliminaciones, necesita una tabla de lápidas.
Tenga en cuenta que cuando realiza una sincronización, debe verificar el desplazamiento de tiempo entre el servidor y el dispositivo móvil, y debe tener un método para resolver conflictos. Las inserciones no son gran cosa (no deberían entrar en conflicto), pero las actualizaciones podrían entrar en conflicto, y una eliminación podría entrar en conflicto con una actualización.
Hay marcos para manejar este tipo de cosas, como Microsoft Sync Framework .
fuente
Apuesto a que absolutamente, sin duda , no puede tener integridad referencial entre los dos. Específicamente, ¿esperan sus usuarios que la aplicación móvil funcione cuando está desconectada?
Hay dos prácticas para esto:
Una es crear registros "provisionales" en el cliente, y luego, cuando los sincronice con el servidor, haga que el sistema central asigne la ID. El cliente puede actualizar el registro local para reflejar eso.
El otro es que distribuye la creación de ID de una manera que (normalmente de forma probabilística) permite a los clientes crear la ID sin colisiones.
Para eso, vaya a UUID: es poco probable que v4 choque.
De lo contrario, considere algo que coloque la ID única del dispositivo móvil en la ID del registro. Por lo tanto, su ID de registro puede ser
${imei}-${local sequence number}
o algo así, donde el IMEI garantiza la unicidad y el número de secuencia local es solo una ID de base de datos secuencial normal.fuente
Además de la respuesta de Daniel Pittman , una posibilidad sería que el servidor asigne a cada cliente una ID de cliente única y que la ID de cliente forme parte de la clave principal.
fuente
Tengo el mismo problema con un proyecto en el que estoy trabajando, la solución en mi caso fue crear un campo anulable adicional en las tablas locales llamadas remote_id. Al sincronizar registros de la base de datos local a la remota si remote_id es nulo, significa que esta fila nunca se ha sincronizado y necesita devolver una identificación única que coincida con la identificación de la fila remota.
En la aplicación cliente, enlazo tablas por el campo _id, de forma remota uso el campo de identificación remota para obtener datos, hacer uniones, etc.
ejemplo localmente:
ejemplo de forma remota:
Este escenario, y sin ninguna lógica en el código, causaría fallas en la integridad de los datos, ya que la tabla client_type puede no coincidir con la identificación real en las tablas locales o remotas, por lo tanto, cada vez que se genera un id_remoto, devuelve una señal a la aplicación cliente. pidiendo actualizar el campo local _id, esto dispara un disparador creado previamente en sqlite que actualiza las tablas afectadas. http://www.sqlite.org/lang_createtrigger.html
1- remote_id se genera en el servidor
2- devuelve una señal al cliente
3- el cliente actualiza su campo _id y dispara un disparador que actualiza las tablas locales que se unen al _id local
Por supuesto, también uso un campo last_updated para ayudar a las sincronizaciones y evitar sincronizaciones duplicadas.
fuente