LINUX.ORG.RU

Синхронизация баз данные


0

0

Хочу сделать такую штуку - на сервере крутиться БД, через web можно редактировать записи.
Есть клиентские приложения, которое загружают даннные с сервера, и клиент может работать без инета только с локальной БД, вносить измениния (удалять, создавать записи) затем загружать данные на сервер. Клиентов может быть несколько.

Такая вот структура:
http://f3ex.narod.ru/sync_db2.png

1. Загрузка из main DB в Slave1
2. Загрузка из mail DB в Slave2
3. Внесение изменений в Main DB
4. Внесение изменений в Slave1
5. Загрузка из Slave1 в Main DB
6. Внесение изменений в Slave2
7. Загрузка из Slave2 в main DB
8. Загрузка из main DB в Slave2

Предполагаются простые 2 таблички. Под "изменением" понимается добавление\удаление\обновление записи в таблице.

Собственно вопрос - есть ли какие-нибудь алгоритмы которые мне смогут помочь в синхронизации баз?

★★

> Загрузка из Slave1 в Main DB

тогда это уже не slave. Если у тебя мускул то можешь попробовать мультимастер сделать, но он асинхронный со всеми вытекающими последствиями.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Неудачно, конечно, применил термин slave. Правильнее Local Base.

Как раз в том то и дело, что не хочу привязываться к мускулу. Зачем мне мускул на ноуте или телефоне? SQlite хватит. Следовательно репликация не мой вариант.

Пока вижу только простой вариант - вести журнал изменений и передавать его при синхронизации в виде yaml/xml файлика.

В случае наличия записи на master и local базе при загрузке вычислять diff и дописывать вконец записи..

f3ex ★★
() автор топика

Когда я вижу такие вещи я всегда думаю об одном: что если в обеих локальных копиях будет сделан, например, update одной и той-же записи, но с разными данными?

legolegs ★★★★★
()
Ответ на: комментарий от f3ex

> Так вот, собственно об этом и речь. Что делать?

Хранить версию записи и инкрементить ее на каждый update, например. Без привязки к задаче трудно советовать, что делать с конфликтами.

SOmni ★★
()
Ответ на: комментарий от SOmni

Приложение типа home-wiki для персональных заметок, how-to. 2 таблицы:
1 (Category): id, parant_id, title
2 (item): id, category_id, body

В body хранится моя статья. К примеру такая запись как - заметки по опциям `ls`.

Я синхронизирую на локальном компьютере с сервера базу. Читаю её локально. Затем вношу изменение конкретно в эту статью. (в примере просто добавляю строчки).

После чего хочу сделать синхронизацию на сервер. В простом случае - можно затереть запись на сервере - локальной записью. Но может быть случай, что я на сервере уже поправил запись или синхронизировал её с базой с третьего компьютера.

Как-то так.

f3ex ★★
() автор топика
Ответ на: комментарий от f3ex

Если данные не важные, то просто затирай. Можно на всякий случай делать бекап затираемого, чтобы если что изредка ручками что нужно вернуть.

Ещё вариант - загружать не всю базу, а только минимально необходимую часть и блокировать её на сервере, не давая делать другие копии.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Помечать записи timestamp-ом. Последний изменивший выигрывает.

При совпадении времени(маловероятно) - тут наверное надо вырабатывать какой-то арбитраж или систему приоритетов.

ef37 ★★
()
Ответ на: комментарий от ef37

изменения до этого может быть внесенего еще из одного клиента, и оно перезатрется...

В общем вот, что я придумал в итоге.

Действительно хранится таймстамп в строке со статьей. Я загружаю базу на локальный компьютер, делаю изменение в статье, timestamp не меняю. Затем загружаю в базу на сервере - если timestamp'ы одинаковые, то перезаписываю измения, а если отличаются - то вывожу на экран разницу локального и серверного варианта и предлагаю вручную составить итоговый вариант - и его загружаю в базу на сервере.

Тут только момент - нужно на локальных клиентах запретить удаление записей, иначе возникнут такие коллизии, что разруливать их будет сложно.

f3ex ★★
() автор топика

Возможно, тебе будет интересен такой (сравнительно неудачный) опыт борьбы с проблемой.

Когда-то хотел в своей аппликухе сделать подобный функционал. Делал на досуге, как следствие, по частям, начиная с той, что казалось "самой сложной". Скоро сразу сделал обобщённый перловый cgi-скрипт для сервера, который через http давал доступ к обобщённому хранилищу обобщённых данных (приемлемых для моего приложения). При этом сервер только обеспечивал контроль версий (при запросе на модификацию данных клиент должен был указать серверу serial number данных, и, если тот не совпадал, транзакция отвергалась, а клиенту приходилось снова делать update. Что, в общем-то, нормально). Соответственно, разрешением коллизий должен был заниматься клиент, исходя из семантики своих данных и логики работы с ними. В общем, как в типичных vcs. Вероятно, лучше даже было взять готовую vcs.

Это алгоритм разрешения коллизий в конечном счёте предоставлялся этому движку (клиентской части движка) самой аппликухой. Так вот, соль в том, что, уже отписав весь этот функционал, я так и не реализовал эту сравнительно тривиальную application-specific логику разрешения коллизий. Мне показалось, что эта логика будет слишком грубой (хотя и приемлемой в большинстве случаев), и я потерял интерес к задаче.

Мораль басни в том, что если захочешь пойти по этому пути, стоит начать с тщательного продумывания и отписывания этой логики. После этого, возможно, подобрать движок будет не проблема.

Кстати, данные в аппликухе были чем-то вроде словаря. Удаление записей при этом можно отслеживать через номера версий.

alexsaa
()
Ответ на: комментарий от alexsaa

сколько лет человечество бьется на этой проблемой - а адекватного решения нет до сих пор, делаю я такой вывод :)

да, задача примерно такая же. Но хочу сделать попытку сделать такое, просто не всегда удобно использовать trac (или что-то wiki-подобное) и будет только один пользователь - я. Но с разных девайсов... Подумал - для счастья нужно только diff будет расковырять и переписать нужную функцию на c++ чтобы на клиенте сразу видеть изменения и править.

> Удаление записей при этом можно отслеживать через номера версий.

Т.е. у тебя хранилась история изменения ? Я не планирую держать списко измений. Насчет удаления конкретно в моем случае может возникнуть следующая ситуация, и пока не решил её:

на 1-й лок. компьютер загружаю базу, потом загружаю на второй базу. На втором я сношу целый под-раздел и вношу измения на сервер (проходит все удачно). Затем я на первом компьютере вношу измения в статью и пытаюсь загрузить на север - и получается что мне нужно проверить не только наличие самой статить для UPDATE а еще и Catogory.parent_id (Catogory.parent_id.parent_id etc)... хотя тут ничего сложного и нет, можно сделать

f3ex ★★
() автор топика
Ответ на: комментарий от f3ex

> > Удаление записей при этом можно отслеживать через номера версий.

> Т.е. у тебя хранилась история изменения ? Я не планирую держать списко измений.

Нет, у меня не было истории. На сервере - только сами данные (в текущем состоянии) и число "version" (либо общее для всей базы, либо для каждого блока отдельно). Версия нужна для организации взаимодействия по шаблону синхронизации без блокировок, известному как "atomic". Если два клиента пытаются послать новые данные, то удастся только модификация первого, после чего version на сервере увеличится на единицу, и тогда второй клиент автоматом получит version collision и будет вынужден загрузить свежие данные с сервера и думать над содержательным разрешением коллизии.

> Затем я на первом компьютере вношу измения в статью и пытаюсь загрузить на север

У меня, наверное, было бы так. В момент отправки на сервер первым же делом выяснится, что сервер уже ушёл далеко вперёд. Тогда первый компьютер запросит текущее состояние интересующего его раздела с сервера и узнает, что этого раздела уже нет. Поскольку раньше раздел был (первый компьютер это помнит), значит, "там" раздел удалили. Итак, первый компьютер видит классическую ситуацию конфликта параллельных операций изменения и удаления. Как ему её разрешать - зависит от задачи, но вообще логично, чтобы доминировало удаление. Тогда он просто выбрасывает свои изменения вместе с блоком данных и считает, что синхронизация выполнена.

alexsaa
()
Ответ на: комментарий от f3ex

> сколько лет человечество бьется на этой проблемой - а адекватного решения нет до сих пор, делаю я такой вывод :)

потому что задача нетривиальна.

true_admin ★★★★★
()

Я б свое в такой ситуации не стал городить.

Посмотри на идеи в http://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5...

Там простым языком написано как лучше и правильнее делать подобные вещи. Как выберешь подходящий вариант - гугли конкретную реализацию.

ИМХО, это наиболее правильный вариант.

VladimirMalyk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.