在两个PostgreSQL服务器之间传输数据

时间:2017-09-03 12:14:29

标签: postgresql networking data-replicator

我有两个PostgreSQL服务器,一个集中式服务器和一个外围服务器。这个想法是外围服务器累积来自同一台机器上运行的各种进程的数据。数据从周边服务器周期性地发送到集中式服务器中(可能每小时一次)。在确认成功的服务器之后,外围服务器将擦除其内容以使其实现尽可能轻量级。

虽然最初这是一个相当直接的场景,其中有许多现有的解决方案,我相信,有一些因素限制了我的选择:

  • 外围服务器和集中式服务器之间的链接可能会一次停机数天,在这种情况下,它只会保留所有数据并重试下一次计划的传输,而且数据量是原来的两倍。

  • 重要的是不要复制任何记录,因此擦除的记录必须与传输的记录完全匹配。

  • 外围服务器很可能在传输过程中累积了额外的数据,因此丢弃并重新创建表是不可行的,因为它会清除一些尚未传输的记录。

    < / LI>

我从几个角度看过这个问题,我得出的结论是,我很有可能试图在这里重新发明轮子,因为有很多方法几乎符合我的需要。因此,我决定采取几步,看看对这种情况的建议是什么。我的问题是:

  • 当链接不可靠时,推荐的转移方法是什么?

  • 有哪些转移验证方法?

  • 当外围数据库在传输过程中仍在累积数据时,如何确保擦除日期与传输的数据完全匹配?

在debian上使用postgresql 9.4.9。

一个想法的粗略轮廓:

  1. 该表格有一个serial列,用于跟踪记录ID。

  2. pg_dump数据到文件。上述序列用于文件名,基本上“这包含XY的所有记录”

  3. 通过rsync等将dumpfile复制到中央服务器。

  4. 集中服务器加载数据,并以某种方式将验证发送回包含序列的外围服务器。请考虑重复几次,以确保以后不会传输重复项。

  5. 外围服务器核实与经过验证的连续出版物有关的所有数据。

  6. 有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您提出的方法是一个合理的起点,但在第一点是有缺陷的。您隐含地假设serial列提供了一些可靠的排序边界。 它没有

  1. Txn 1开始
  2. Txn 2开始
  3. Txn 1获得序列值4
  4. Txn 2获得序列值5
  5. Txn 2提交
  6. Txn 3开始
  7. Txn 3复制数据
  8. Txn 3通知最高承诺值为5
  9. Txn 1提交
  10. Txn 3删除id <= 5
  11. 的所有数据

    糟糕。 Txn 3删除了id = 4,但它不会被复制。通过生成txn3 SERIALIZABLE来修复这种特殊情况,但是如果改为Txn3提交而其他一些tx txn4执行删除,则会出现问题。

    为了安全起见,您必须在5到7之间的某个位置添加一个屏障,其中LOCK TABLE ... IN EXCLUSIVE MODE并等待获取锁定。这确保没有未完成的写入,一切都已提交。您现在可以相信,以后不能提交低于最高值读取的值。

    不同的(新启动的)xact,然后pg_export_snapshot

    导出快照后,您可以回滚获取锁定的xact并让写入继续。

    保留导出快照的xact。将快照ID传递给pg_dump --snapshot,因此它会从您知道最高提交ID的虚拟时间点转移 。您必须保持xact保持快照打开,直到转储完成,但写入可以在同一时间继续。

    现在,您可以安全DELETE FROM ... WHERE id < x查看保持锁定的x值。您知道,由于导出的快照,您没有转储任何具有更高ID的内容。而且你知道,由于锁定,你不会错过任何以较低ID提交的东西。

    看起来很复杂?

    相反,我建议使用PostgreSQL的逻辑解码功能。使用逻辑解码的工具pglogical具有使您想要做的事情相对容易的功能;它摆脱了排序问题,并保证行复制完全一次。可以很容易地将其设置为复制插入,但不能删除,因此您可以偶尔DELETE FROM mytable

    (当然,我是pglogical开发团队及其相关工具BDR的一部分,所以我有偏见)。

    您可能面临的主要问题是您必须保留更多数据,因为您需要保留WAL,而不仅仅是表格内容。 (从技术上讲,您可以在DELETE编辑后立即INSERT数据,并且它会很好地复制,但您可能不会想要这样做。因此,如果磁盘空间存在问题,您可能希望采用转储方法。但pglogical3中有一些重大改进会使这个问题消失。