Postgresql 在postgres上使用两阶段提交

Postgresql 在postgres上使用两阶段提交,postgresql,two-phase-commit,Postgresql,Two Phase Commit,如果a在“db1”中有一个名为“t1”的表,在“db2”中有另一个名为“t2”的表,我需要在这两个表上插入一条记录,否则会失败 连接到db1,我想我应该键入这个 BEGIN; PREPARE TRANSACTION 'pepe'; -- this says the manual that makes your transaction gets stored on disk, so what is the purpose if i can't use it from another databas

如果a在“db1”中有一个名为“t1”的表,在“db2”中有另一个名为“t2”的表,我需要在这两个表上插入一条记录,否则会失败

连接到db1,我想我应该键入这个

BEGIN;
PREPARE TRANSACTION 'pepe'; -- this says the manual that makes your transaction gets stored on disk, so what is the purpose if i can't use it from another database?)

insert into t1 (field) values ('a_value');

COMMIT PREPARED 'pepe'
连接到db2,我想

BEGIN;
PREPARE TRANSACTION 'pepe'; -- this fails (the name of the transacttion, what is the meaning, what is use for?)
 -- It complains about this "ERROR:  transaction identifier "pepe" is already in use"

insert into t2 (field) values ('another_value');

COMMIT PREPARED 'pepe'
正如你可能看到的,我不知道如何在postgres上使用两阶段提交

TL;DR

我不知道如何在同一RDBMS中的不同DB上执行同步命令

我已经读到,对于跨两个或多个不相关的postgres数据库的同步工作,我们可以使用所谓的“两阶段提交”协议的实现

所以我开始试着看看人们是如何在postgres中使用它们的,我没有看到任何实际的例子,我最多只能看到一个家伙,他试图用几个连接到不同数据库的postgres客户端进行实验,以模拟并行运行的多进程,对几个数据库执行操作,这些操作应该以感激的方式(全部提交)或可怕的方式(全部回滚)结束

我看到的其他来源包括:

  • (此来源) 很好地解释了协议,但真的让我想知道谁在哪里 我的“协调员”以及如何向“参与者”发送消息……我 仅获得了
    准备事务
    提交准备
    准备回滚
    由我处理的命令)
  • (来自golang客户端应用程序)
拜托,我真的很困惑,我希望没有名字的马能出现在这里,启发我(就像过去发生的那样)或任何其他可以帮助我的慈善灵魂

提前谢谢

决议(在Laurenz的回答之后) 连接到db1,以下是要执行的sql行:

BEGIN;
-- DO THINGS TO BE DONE IN A ALL OR NOTHING FASHION
-- Stop point --    
PREPARE TRANSACTION 't1';
COMMIT PREPARED 't1' || ROLLBACK PREPARED 't2' (decision requires awareness and coordination)
BEGIN;
-- DO THINGS TO BE DONE IN A ALL OR NOTHING FASHION
-- Stop point --  
PREPARE TRANSACTION 't2';

COMMIT PREPARED 't2' || ROLLBACK PREPARED 't2'
同时连接到db2,这些将是要执行的脚本:

BEGIN;
-- DO THINGS TO BE DONE IN A ALL OR NOTHING FASHION
-- Stop point --    
PREPARE TRANSACTION 't1';
COMMIT PREPARED 't1' || ROLLBACK PREPARED 't2' (decision requires awareness and coordination)
BEGIN;
-- DO THINGS TO BE DONE IN A ALL OR NOTHING FASHION
-- Stop point --  
PREPARE TRANSACTION 't2';

COMMIT PREPARED 't2' || ROLLBACK PREPARED 't2'
  • --停止点--
    是协调进程(例如 执行该语句的应用程序,或psql背后的人员 客户端控制台或pgAdminII)应停止执行这两个命令 脚本(实际上不执行任何进一步的指令,这就是我所说的停止)

  • 然后,首先在db1上(然后在db2或viceversa上) 协调进程(无论是否为人工)必须在每个连接上运行
    PREPARE TRANSACTION

    • 如果其中一个失败,那么协调器必须在已经准备好事务的数据库上运行
      ROLLBACK PREPARED
      ,在其他数据库上运行
      ROLLBACK
    • 如果没有人失败,协调员必须在所有涉及的数据库上运行COMMIT PREPARED,这是一个永远不会失败的操作(就像当你走出家门一步,所有东西都被正确地设置为安全退出时,家里就已经存在)

    • 我想你误解了
      准备交易

      该语句结束事务的工作,也就是说,它应该在所有工作完成后发出。其思想是,
      PREPARE TRANSACTION
      执行提交期间可能失败的所有操作,但提交本身除外。这是为了保证后续的
      提交准备
      不会失败

      其思想是处理如下:

      • 在分布式事务中涉及的所有数据库上运行
        START TRANSACTION

      • 做所有的工作。如果有错误,
        回滚
        所有事务

      • 在所有数据库上运行
        PREPARE TRANSACTION
        。如果在任何地方失败,请在已经准备好事务的数据库上运行
        ROLLBACK PREPARED
        ,在其他数据库上运行
        ROLLBACK

      • 一旦
        PREPARE TRANSACTION
        在任何地方都成功,在所有涉及的数据库上运行
        COMMIT PREPARED

      这样,您就可以跨多个数据库保证“全部或全部不存在”

      这里我没有提到的一个重要组件是分布式事务管理器。它是一个软件,可以持久地存储上述算法处理当前的位置,以便在崩溃后可以清理或继续提交

      如果没有分布式事务管理器,两阶段提交就没有多大价值,而且实际上是危险的:如果事务停留在“准备”阶段但尚未提交,它们将继续持有锁,并且(在PostgreSQL的情况下)即使在服务器重新启动时也会阻止autovacuum工作,因此,此类事务必须是持久的


      这很难做到正确。

      我想这可以帮助我,我花了很多时间查看两阶段提交,而不是准备事务…:上面的链接有一个很奇怪的例子,我想,根据Laurenz的回答,它不是准备两个事务,而是使用两个数据库…“我想你误解了准备事务”如果你没有事务管理器,最好不要使用分布式事务。好的,我知道了,我猜我用来连接数据库的应用程序可能就是所谓的事务管理器的监管者流程,不是吗?但是,再一次。。让我们在这里慢慢来!我们有一个在Golang编程的应用程序,我们使用该应用程序在数据库中创建我们的东西。当然可以。但是,它最好确保保存这些信息,以便在崩溃后恢复工作。否则,您最终会遇到“卡住”的准备事务。是的,看起来您做对了。请注意,“如何编写分布式事务管理器?”是一个过于宽泛的问题。试着获取关于这个主题的文献。