Добрый день,
Есть центральная локальная БД (главная), есть БД с похожей структурой на сайте. Необходимые обновления (например обновления или расширение прайс-листа) шлются из центральной БД на удаленную через веб-сервис. Шлю партиями, например по 1000 строк за раз.
Проблема в том, что так как пересылка данных идет через интернет, а так же нет контроля удаленного сервера (т.е. он может просто уйти в даун или еще что угодно в общем-то), то возможны какие-либо ошибки, которые приведут к рассинхронизации, потере некоторых данных на удаленной БД.
Мне предложили сделать версионность, т.е. на удаленной БД в таблице вводится колонка version, строки теперь только добавляются (а не добавляются и обновляются) с выставлением поля version на 1 больше версии при последнем удачном апдейте. В случае возникновения ошибки — производим откат, т.е. удаляем все строки с нужным номером версии. При выборке же данных (например показе прайс-листа на сайте) выбираем строку с максимальной версией, т.е. например в случае mysql так:
SELECT * FROM price WHERE ... ORDER BY version DESC LIMIT 1
У данного подхода есть несколько минусов, главным из которых является разрастание БД:
если например в прайсе часто будут обновления по несколько сотен тысяч строк, что в принципе возможно — то таблица прайса будет довольно разрастаться, со всеми вытекающими (требования к месту на сайте, скорость работы с этой таблицей и т.д.)
Вопрос:
Может кто-то предложит более лучший (по каким-либо параметрам) подход к обеспечению надежности синхронизации?
Заранее спасибо.
Re: Обеспечение надежности при синхр-ии таблиц БД чере вебсе
MC>Мне предложили сделать версионность, т.е. на удаленной БД в таблице вводится колонка version, строки теперь только добавляются (а не добавляются и обновляются) с выставлением поля version на 1 больше версии при последнем удачном апдейте. В случае возникновения ошибки — производим откат, т.е. удаляем все строки с нужным номером версии. При выборке же данных (например показе прайс-листа на сайте) выбираем строку с максимальной версией, т.е. например в случае mysql так:
По-моему, вполне рабочий вариант. Можно его еще слегка упростить. Заводим поле status с двумя значениями — ready и new
1) Заливаем данные, указывая статус new
1.5) в случае ошибки удаляем их по статусу
2) Одной транзакцией (ваша БД умеет транзакции?) стираем данные со статусом ready и меняем статус оставшихся данных с new на ready
Если транзакции нельзя, можно слегка усложнить алгоритм.
Re[2]: Обеспечение надежности при синхр-ии таблиц БД чере ве
Здравствуйте, Mikhail Polykovsky, Вы писали:
MC>>Мне предложили сделать версионность, т.е. на удаленной БД в таблице вводится колонка version, строки теперь только добавляются (а не добавляются и обновляются) с выставлением поля version на 1 больше версии при последнем удачном апдейте. В случае возникновения ошибки — производим откат, т.е. удаляем все строки с нужным номером версии. При выборке же данных (например показе прайс-листа на сайте) выбираем строку с максимальной версией, т.е. например в случае mysql так:
MP>По-моему, вполне рабочий вариант. Можно его еще слегка упростить. Заводим поле status с двумя значениями — ready и new MP>1) Заливаем данные, указывая статус new MP>1.5) в случае ошибки удаляем их по статусу MP>2) Одной транзакцией (ваша БД умеет транзакции?) стираем данные со статусом ready и меняем статус оставшихся данных с new на ready
MP>Если транзакции нельзя, можно слегка усложнить алгоритм.
Привет. Можно подумать вот над какой схемой
Привет. Можно подумать вот над какой схемой
1. Клиент получает порцию данных и обновляет записи в своей локальной б.д.
2. Клиент шлет серверу подтверждение что пакет обновлений был успешно обработан.
3. Сервер помечает, что такие-то записи такому-то клиенту слать больше не надо
4. Сервер готовит следующую порцию обновлений.
Что касается п3. то вместе с каждой записью можно хранить битовую или текстовую маску . Позиция соотв. порядковому номеру клиента. 0 — запись не была получена клиентом., 1 — запись была получена клиентом.
При обновлении ценный на сервере все позиции выставляются в 0.
Напрмер
HDD seagate baracuda 250 баксов 1010000000
в данной случае новую цену получили 0-й и 2-й клиенты
Так же можно можно вести доп. таблицу с жуналом доставки или что-нить подобное.
Re: Обеспечение надежности при синхр-ии таблиц БД чере вебсе
Здравствуйте, MozgC, Вы писали:
MC>Добрый день, MC> Есть центральная локальная БД (главная), есть БД с похожей структурой на сайте. Необходимые обновления (например обновления или расширение прайс-листа) шлются из центральной БД на удаленную через веб-сервис. Шлю партиями, например по 1000 строк за раз.
Сервер
1. На каждого удаленного клиента выделяешь курсор данных.
2. Отправляешь пачку данных.
3. Если получил подтверждение что все прошло успешно и например КС совпала, переводит курсор на след. порцию данных, нет повторяет передачу пакета.
Клиент
1. Принимает данные, в цикле для каждой записи
1. update
2. если поймал исключение, запись не существует, insert
3. если и здесь исключение fatal error на сервер
4. если все нормально, подсчитал например КС
5. Закончил прием данных, отправляет на сервер КС или fatal error
выигрываешь в точной копии данных, даже при добавлении новых записей, проиграешь в скорости, т.к. нельзя сделать пакетную обработку на удаленном клиенте
Re[3]: Обеспечение надежности при синхр-ии таблиц БД чере ве
Здравствуйте, MindWrapper, Вы писали:
MW>Что касается п3. то вместе с каждой записью можно хранить битовую или текстовую маску . Позиция соотв. порядковому номеру клиента. 0 — запись не была получена клиентом., 1 — запись была получена клиентом. MW>При обновлении ценный на сервере все позиции выставляются в 0. MW>Напрмер MW>HDD seagate baracuda 250 баксов 1010000000 MW>в данной случае новую цену получили 0-й и 2-й клиенты
Изначально кривой вариант. Кол-во клиентов 500. Как будете делать?
А завтра добавилось еще 15 клиентов. Варианты?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[4]: Обеспечение надежности при синхр-ии таблиц БД чере ве
Здравствуйте, denisio_mcp, Вы писали:
_>Здравствуйте, MindWrapper, Вы писали:
MW>>Что касается п3. то вместе с каждой записью можно хранить битовую или текстовую маску . Позиция соотв. порядковому номеру клиента. 0 — запись не была получена клиентом., 1 — запись была получена клиентом. MW>>При обновлении ценный на сервере все позиции выставляются в 0. MW>>Напрмер MW>>HDD seagate baracuda 250 баксов 1010000000 MW>>в данной случае новую цену получили 0-й и 2-й клиенты
_>Изначально кривой вариант. Кол-во клиентов 500. Как будете делать? _>А завтра добавилось еще 15 клиентов. Варианты?
вариаций на тему может быть множество. описанный вариант подходит например для госучреждений,
организационная структура которых более или менее статична.
Если структура имеет тенденцию меняться, то можно придумать что-нибудь более гибкое, скажем, дополнительную таблицу,
в которой бы хранились данные о том, какую запись из какой таблицы какому клиенту нужно доставить. Что-нибудь в этом духе.
Re[5]: Обеспечение надежности при синхр-ии таблиц БД чере ве
Сделал так:
В центральной локальной БД создал отдельную таблицу всего лишь с одним столбцом и строкой — максимальным значением timestamp из последней удачной синхронизации. При синхронизации выбираются все позиции с более поздним timestamp. Если возникает ошибка — просто сообщаем об ошибке, с предложением попробовать еще раз попозже либо сообщить кому-надо . И при следующей синхронизации мы опять постараемся захватить все с более поздним timestamp (т.к. мы его не изменили). Если же ошибки нет — то обновляем значение в этой отдельной таблице, и уже при следующей выборке будем читать записи новее записанного timestamp.
Надеюсь понятно объяснил, если кому вдруг интересно или пригодится...
Такое решение понравилось простотой и скоростью реализации.
Re[6]: Обеспечение надежности при синхр-ии таблиц БД чере ве
Здравствуйте, MozgC, Вы писали:
MC>Всем большое спасибо за участие в теме!
MC>Сделал так: MC>В центральной локальной БД создал отдельную таблицу всего лишь с одним столбцом и строкой — максимальным значением timestamp из последней удачной синхронизации. При синхронизации выбираются все позиции с более поздним timestamp. Если возникает ошибка — просто сообщаем об ошибке, с предложением попробовать еще раз попозже либо сообщить кому-надо . И при следующей синхронизации мы опять постараемся захватить все с более поздним timestamp (т.к. мы его не изменили). Если же ошибки нет — то обновляем значение в этой отдельной таблице, и уже при следующей выборке будем читать записи новее записанного timestamp.
MC>Надеюсь понятно объяснил, если кому вдруг интересно или пригодится...
MC>Такое решение понравилось простотой и скоростью реализации.
А кто и когда вычисляет таймстапм?
Re[7]: Обеспечение надежности при синхр-ии таблиц БД чере ве
Н>Ойойой. Откройте для себя MVC/MVP, ORM/Result Set Mapper и разделение на слои.
Я открыл Просто работал всегда либо вдвоем, либо вообще удаленно. Но сейчас уже в ближайших планах почитать Фаулера и новую книгу Нильсона. А вообще может кто поделится ссылкой или советом где есть хорошие примеры разделения на слои? Но не в абстрактных предложениях или несвязанных отрывках кода, а где бы действительно рассматрировалась многослойная архитектура бизнес-проекта с хорошими примерами, после чего можно было бы имееть четкое понимание и представление?
Re[11]: Обеспечение надежности при синхр-ии таблиц БД чере в
при любом добавдлении/изменении записи в любой таблице обновляется поле last_update. операция посылки обновления выполняется ежедневно, но при этом выбирает данные, обновлённые за последнюю неделю. при этом синхронизируемые таблицы/записи меняются только в центральном офисе (скажем, это дилерский прайслист, состояние запасов на центр. складе и т.п.), поэтому конфликтов обнолвения не порисходит. плюс есть таблица deleted, куда заносятся tablename+id удалённых записей и дата удаления — из неё выборка ес-но делается тоже
когда что-то идёт совсем не так — можно просто послать данные за целый год