Postgres中的离线有限多主人

时间:2011-10-05 22:16:50

标签: postgresql replication database-replication

站点A将生成一组记录。每晚他们将备份他们的数据库并将其ftp到站点B.站点B根本不会修改这些记录,但会添加更多记录,而其他表格将创建FK到站点A的记录。

因此,基本上,我需要设置一个系统来从站点A的转储中获取所有增量更改(主要是插入和更新,但有些删除可能)并在站点B上应用它们。

此时,我们正在使用Postgres 8.3,但如果有价值可以升级。

我相信我可以用Bucardo相对直接地做到这一点,但在设置一个linux盒子来测试它之前,我很想听听替代品(或Bucardo的确认)。

1 个答案:

答案 0 :(得分:3)

大多数复制解决方案都可以解决问题。 Postgres Wiki有一个chapter on the topic。但你的情况很简单。我只想使用 dblink 这是从我的工作实现中得出的:

  1. 主数据库中创建一个返回更新行的视图 我们称之为myview

  2. slave db 中为每个表创建一个函数,该函数通过dblink获取行:

  3. CREATE OR REPLACE FUNCTION f_lnk_mytbl()
      RETURNS TABLE(col_a integer, col_b text, col_c text) AS
    $func$
       SELECT *
       FROM   public.dblink('SELECT col_a, col_b, col_c FROM myview')
                          AS b(col_a integer, col_b text, col_c text);
    $func$  LANGUAGE sql SECURITY DEFINER;
    
    REVOKE ALL ON FUNCTION f_lnk_mytbl() FROM public;
    GRANT EXECUTE ON FUNCTION f_lnk_mytbl() TO my_user;
    
    1. slave db 中的另一个函数中使用上述函数来建立和关闭服务器连接。
    2. CREATE OR REPLACE FUNCTION f_mysync()
        RETURNS void AS
      $func$
      BEGIN
         PERFORM dblink_connect(
                'hostaddr=123.45.67.89 port=5432 dbname=mydb user=postgres password=secret');
      
         -- Fetch data into local temporary table for fast processing.
         CREATE TEMP TABLE tmp_i ON COMMIT DROP AS
         SELECT * FROM f_lnk_mytbl();
      
         -- *Or* read local files into temp tables with COPY so you don't need dblink.
         -- UPDATE what's already there (instead of DELETE, to keep integrity).
         UPDATE mytbl m
         SET   (  col_a,   col_b,   col_c) =
               (i.col_a, i.col_b, i.col_c)
         FROM   tmp_i i
         WHERE  m.id = i.id
         AND   (m.col_a, m.col_b, m.col_c) IS DISTINCT FROM
               (i.col_a, i.col_b, i.col_c);
      
         -- INSERT new rows
         INSERT INTO mytbl
         SELECT * FROM tmp_i i
         WHERE  NOT EXISTS (SELECT 1 FROM mytbl m WHERE m.id = i.id);
      
         -- DELETE anything? More tables?
      
         PERFORM dblink_disconnect();
      END
      $func$  LANGUAGE plpgsql SECURITY DEFINER;
      
      REVOKE ALL ON FUNCTION f_mysync() FROM public;
      GRANT EXECUTE ON FUNCTION f_mysync() TO my_user;
      
      1. 现在,这个电话就是您所需要的。以超级用户或my_user呼叫。安排一个cronjob或其他东西。
      2. SELECT f_sync_mytbl();
        

        在PostgreSQL 9.1或更高版本中,还有新的CREATE FOREIGN TABLE。可能会更优雅。