Как заставить Mobilink синхронизировать таблицы, чтобы самая последняя обновленная таблица не была перезаписана?

StackOverflow https://stackoverflow.com/questions/941835

Вопрос

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

Это было полезно?

Решение

Прямо сейчас вы используете разрешение конфликтов по умолчанию на сервере 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:

МобиЛинк - Администрирование сервера

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

Разрешение конфликтов

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

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top