这是场景。我有一个 Oracle 统一数据库。我正在使用 Mobilink 将 Oracle 与手持设备上使用的 SqlAnywere 数据库同步。如果用户 A 将其手持设备上的远程数据库中的一条记录更改为“首先更新”,然后 10 分钟后,用户 B 将其手持设备上的同一记录更新为“第二次更新”,我希望统一数据库始终显示“第二次更新”两个设备已同步。目前,如果用户B 在用户A 之前同步,统一数据库将显示“先更新”。

有帮助吗?

解决方案

现在,您在 MobiLink 服务器中使用默认冲突解决方案,因此默认情况下最后一次同步获胜。您需要实施自己的冲突解决方案来处理此问题。

这需要在远程数据库上发生两件事:

1) 远程数据库的表中需要有一列与统一数据库同步,跟踪记录在远程站点更新的时间。

2) 您必须信任远程站点的系统时钟。如果人们弄清楚如何解决冲突,并且希望确保他们的数据赢得冲突,则没有什么可以阻止用户将远程设备上的系统时间更改为下周,更新他们的数据,将系统时间更改回来以及然后同步。

在整合时,您需要实施冲突解决方案,这并不难。只要您的表不包含任何 blob,您就可以在表的 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

其他提示

假设您已实现基于时间戳的下载或快照下载,如果自上次同步以来另一个远程更新了整合,则远程将更新以匹配整合。

顺便说一句,如果您设置了同步模型(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