并发同步,避免密钥冲突

时间:2018-10-04 15:40:41

标签: sql postgresql

我有多个使用日志表保持同步的数据库:

source bigint,
tick serial,
data text

primary key (source, tick)

例如,天真的同步方法是在我的第二个源上同步来自第一个源的数据:

insert into log_table (source, tick, data)
select source, tick, data
from other_db.log_table
where source = 1
and tick > (select max(tick) from log_table where source = 1)

我已经简化了示例。实际上,它使用dblink查询其他数据库,但我认为这与该问题无关。我遇到的问题是,如果我有多个线程进行同步,则会遇到密钥冲突。

我目前的工作是检测密钥冲突并简单地重试。重试很可能不会处理任何事情,因为另一个线程会完成工作。我想知道是否会有更有效的方法。

1 个答案:

答案 0 :(得分:1)

如果您使用的是Postgres 9.6或更高版本,则可以尝试upsert语句on duplicate key do nothing(或on duplicate key do update取决于您要执行的操作)

https://www.postgresql.org/docs/9.6/static/sql-insert.html

与您的查询

insert into log_table (source, tick, data)
select source, tick, data
    from other_db.log_table
    where source = 1
        and tick > (select max(tick) from log_table where source = 1)
on duplicate key do nothing

或者您可以尝试使用存储过程,在其中可以使用行级锁 https://www.postgresql.org/docs/9.6/static/explicit-locking.html

例如,您可以创建一个看起来像这样的函数

create or replace function tick_update() returns void
language plpgsql as
$f$
declare
  max_tick integer;
begin
    select max(tick) into max_tick from log_table where source = 1;
    for rec in 
        select source, tick, data
        from other_db.log_table
        where source = 1
            and tick > max_tick
        for update
    loop
    insert into log_table (source, tick, data) values (rec.source, rec.tick, rec.data)
    end loop;
end
$f$