Как заставить Mobilink синхронизировать таблицы, чтобы последняя обновленная таблица не перезаписывалась? - PullRequest
2 голосов
/ 03 июня 2009

Вот сценарий. У меня есть консолидированная база данных Oracle. Я использую Mobilink для синхронизации Oracle с базой данных SqlAnywere, которая используется на контроллере. Если пользователь A меняет запись в удаленной БД на своем портативном устройстве на «сначала обновлен», а затем через 10 минут пользователь Б обновляет ту же запись на своем портативном устройстве на «обновленную секунду», я хочу, чтобы консолидированная база данных всегда показывала «обновленную секунду» после два устройства синхронизированы. В настоящее время, если userB синхронизируется перед userA, в консолидированной базе данных будет указано «сначала обновлено».

Ответы [ 2 ]

4 голосов
/ 03 июня 2009

В данный момент вы используете разрешение конфликтов по умолчанию на сервере MobiLink, поэтому по умолчанию последняя синхронизация выигрывает. Для этого вам необходимо реализовать собственную схему разрешения конфликтов.

Для этого потребуется две вещи в удаленной базе данных:

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

2) Вам придется доверять системным часам на удаленных сайтах. Если люди выясняют, как разрешаются конфликты, и хотят, чтобы их данные побеждали в конфликте, то ничто не мешает пользователю изменить системное время на своем удаленном устройстве на следующую неделю, обновить свои данные, изменить системное время и затем синхронизация.

В консолидированном, вам нужно реализовать разрешение конфликтов, что не так сложно. Пока ваша таблица не содержит больших двоичных объектов, вы можете записать разрешение конфликта в событие upload_update для этой таблицы. Давайте предположим, что таблица в удаленной базе данных выглядит следующим образом:

create table Admin (
  admin_id           bigint default global autoincrement(1000000) primary key,
  data               varchar(64) not null,
  rem_last_modified  timestamp not null default timestamp
);

Давайте также предположим, что таблица в консолидированной форме выглядит очень похожей, но в ней есть еще один последний измененный столбец для отслеживания изменений строк в консолидированной.

create table Admin (
  admin_id           bigint default global autoincrement(1000000) primary key,
  data               varchar(64) not null ,
  rem_last_modified  timestamp not null default ‘1900-01-01’,
  cons_last_modified timestamp default timestamp
);

Как правило, ваше событие upload_update будет выглядеть примерно так:

call ml_add_table_script( 'v1', 'Admin', 'upload_update',
'update Admin set data = {ml r.data}, 
              rem_last_modified = {ml r.rem_last_modified}  
 where admin_id = {ml r.admin_id}'
);

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

call ml_add_table_script( 'v1', 'Admin', 'upload_update',
'call admin_upload_update( {ml r.admin_id}, 
    {ml r.data}, {ml r.rem_last_modified}, 
    {ml o.data}, {ml o.rem_last_modified}’
);

Ключ к вашей хранимой процедуре заключается в том, что мы собираемся выполнить обновление, но условие where обновления будет включать в себя как значения первичного ключа, так и старые значения строки из удаленной базы данных. Если кто-то изменил строку в объединенном, это обновление обновит ноль строк, и мы знаем, что возникает конфликт. Если он обновляет строку, то не было никакого конфликта. Ваша хранимая процедура будет выглядеть примерно так (псевдо-SQL ниже):

create procedure admin_upload_update ( 
    @admin_id bigint, 
    @new_data varchar(64), 
    @new_rem_lmod timestamp,
    @old_data varchar(64), 
    @old_rem_lmod timestamp 
)
begin
    declare @cur_rem_lmod timestamp;
    update admin set data = @new_data, rem_last_modified = @new_rem_lmod
     where admin_id = @admin_id 
       and data = @old_data 
       and rem_last_modified = @old_rem_lmod;
    if @@rowcount = 0 then
        // conflict !!
        select rem_last_modified into @cur_rem_lmod 
          from admin where admin_id = @admin_id;
        if @new_rem_lmod > @cur_rem_lmod then
            // update using new_data and new_rem_lmod
        else 
            // do nothing, current values in cons wins
        end if;
    end if;  
end;

Подробнее о разрешении конфликтов см. В следующем разделе документации v10:

MobiLink - Администрирование сервера

Методы синхронизации

Обработка конфликтов

http://dcx.sybase.com/index.php#http%3A%2F%2Fdcx.sybase.com%2Fhtml%2Fdbmlen10%2Fml-conflicts-synch.html

2 голосов
/ 04 июня 2009

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

Кстати, требуемый тип разрешения конфликтов доступен, если вы настроили модель синхронизации (http://dcx.sybase.com/index.php#http%3A%2F%2Fdcx.sybase.com%2Fhtml%2Fdbmgen10%2Fmg-mg-about-s-5060632a.html), доступна в версии 10 и выше. Либо в мастере создания модели синхронизации, либо на странице сопоставлений после После создания модели вы можете выбрать, хотите ли вы обнаруживать конфликты на основе строк или столбцов, а также разные типы разрешения конфликтов. То, что вам нужно, соответствует параметру разрешения конфликтов «отметка времени», в котором вы выбираете существующий столбец отметки времени. *

К вашему сведению, мастер объясняет параметры больше, чем страница Mappings, поэтому я рекомендую сначала изучить эти параметры в мастере. Обратите внимание, что если параметр «Новые выигрыши с использованием сохраняемого вами столбца метки времени» недоступен, это означает, что в синхронизированных таблицах нет столбца метки времени.

Создав модель, вы можете просмотреть созданные сценарии на странице События. Когда вы закончите настройку модели, вы развернете ее для создания SQL и пакетных файлов и / или применения SQL непосредственно к базам данных.

...