Так что у меня относительно простая система. Мобильный клиент создает записи в базе данных SQLite , что я хотел бы синхронизирован на удаленный сервер SQL (который совместно с другими мобильными клиентами) . Поэтому, когда я создаю новую запись в таблице sqlite телефона, я затем отправляю это изменение в свою удаленную службу через RESTful API. Проблема, с которой я столкнулся, заключается в том , как мне упорядочить первичные ключи, чтобы в данных не было коллизий (т. Е. Запись в телефоне имеет тот же первичный ключ, что и совершенно другая запись на сервере). Какова обычная «лучшая практика» для ссылки на запись на клиенте и для ссылки на ту же запись на сервере?
sql
web-services
JoeCortopassi
источник
источник
Ответы:
Обычной практикой является структурирование базы данных с помощью
uniqueidentifier
ключей (иногда называемых UUID или GUID). Вы можете создать их в двух местах, не опасаясь столкновения.Затем ваше мобильное приложение должно синхронизировать таблицы фактов с сервера, прежде чем вы сможете создавать новые строки. Когда вы создаете новые строки, вы делаете это локально, и при повторной синхронизации новые строки добавляются на сервер. Вы можете сделать то же самое с обновлениями и удаляет тоже.
Чтобы отслеживать вставки, вам нужно создать метку времени в ваших строках. Чтобы отслеживать обновления, вам нужно отслеживать отметку времени LastUpdate в ваших строках. Для отслеживания удалений вам нужна таблица надгробий.
Обратите внимание, что когда вы делаете синхронизацию, вам нужно проверить смещение времени между сервером и мобильным устройством, и вам нужно иметь метод для разрешения конфликтов. Вставки не имеют большого значения (они не должны конфликтовать), но обновления могут конфликтовать, а удаление может конфликтовать с обновлением.
Существуют фреймворки для таких вещей, такие как Microsoft Sync Framework .
источник
Могу поспорить, что вы, безусловно, не можете иметь ссылочную целостность между ними. В частности, ожидают ли ваши пользователи, что мобильное приложение будет работать, когда оно отключено?
Для этого есть две практики:
Одним из них является создание «временных» записей на клиенте, а затем при синхронизации их с сервером центральная система назначает идентификатор. Клиент может обновить локальную запись, чтобы отразить это.
Другая причина заключается в том, что вы распространяете создание идентификатора таким образом, который (обычно вероятностно) позволяет клиентам создавать идентификатор без коллизий.
Для этого перейдите к UUID - v4 вряд ли столкнется.
В противном случае рассмотрим что-то, что помещает уникальный идентификатор мобильного устройства в идентификатор записи. Таким образом, ваш идентификатор записи может быть
${imei}-${local sequence number}
чем-то вроде того, где IMEI обеспечивает уникальность, а локальный порядковый номер - это просто обычный последовательный идентификатор базы данных.источник
В дополнение к ответу Даниэля Питтмана , одна из возможностей была бы для сервера - назначить каждому клиенту уникальный идентификатор клиента и сделать идентификатор клиента частью первичного ключа.
источник
У меня та же проблема с проектом, над которым я работаю, в моем случае я решил создать дополнительное пустое поле в локальных таблицах с именем remote_id. При синхронизации записей из локальной базы данных в удаленную, если значение remote_id равно нулю, это означает, что эта строка никогда не синхронизировалась и должна возвращать уникальный идентификатор, соответствующий идентификатору удаленной строки.
В клиентском приложении я связываю таблицы с помощью поля _id, удаленно использую поле удаленного идентификатора для извлечения данных, выполнения объединений и т. Д.
пример локально:
пример удаленно:
Этот сценарий, без какой-либо логики в коде, может привести к сбоям целостности данных, так как таблица client_type может не совпадать с реальным идентификатором в локальной или удаленной таблицах, поэтому всякий раз, когда генерируется remote_id, он возвращает сигнал клиентскому приложению при запросе обновления локального поля _id запускается ранее созданный триггер в sqlite, обновляющий затронутые таблицы. http://www.sqlite.org/lang_createtrigger.html
1- remote_id генерируется на сервере
2- возвращает сигнал клиенту
3 - клиент обновляет свое поле _id и запускает триггер, который обновляет локальные таблицы, которые присоединяются к локальному _id
Конечно, я использую также поле last_updated, чтобы помочь синхронизации и избежать дублирования синхронизаций.
источник