-1

我们都知道,我们总是可以将数据库调用包装在事务中(有或没有适当的 ORM),形式如下:

$con = Propel::getConnection(EventPeer::DATABASE_NAME);
try {
    $con->begin();
    // do your update, save, delete or whatever here.
    $con->commit();
} catch (PropelException $e) {
    $con->rollback();
    throw $e;
}

这种方式可以保证如果事务失败,数据库会恢复到正确的状态。

但问题是,假设当我进行事务时,除了该事务之外,我还需要更新另一个数据库(例如,当我更新 databaseA 中的列中的条目时,databaseB 中的列中的另一个条目必须是更新)。如何处理这种情况?

假设这是我的代码,我有三个需要更新的数据库(dbA、dbB、dbc):

$con = Propel::getConnection("dbA");
try {
    $con->begin();
    // update to dbA
    // update to dbB
    //update to dbc
    $con->commit();
} catch (PropelException $e) {
    $con->rollback();
    throw $e;
}

如果 dbc 失败,我可以回滚 dbA 但不能回滚 dbb。

我认为这个问题应该与数据库无关。由于我使用的是 ORM,所以这也应该是独立于 ORM 的。

更新:一些数据库事务包装在 ORM 中,一些使用裸 PDO、oledb(或任何提供数据库调用的最低限度语言)。所以我的解决方案必须注意这一点。

任何想法?

4

3 回答 3

1

首先,一些数据库支持分布式事务协议,允许所有 dbA、dbB 和 dbC 一次参与同一个事务。如果你的,使用它:)

但是,如果做不到这一点,您将需要实现自己的分布式事务协议,例如两阶段提交Paxos。这些协议很复杂,但这种复杂性是绝对必要的,所以不要试图偷工减料 :) 我建议在尝试实现类似的东西之前遵循这些维基百科链接中列出的参考资料并阅读它们。

于 2009-10-23T04:03:55.130 回答
0

您需要一个支持分布式事务的 DBMS 。这些正是您所需要的:它们在多个系统中强制执行开始/提交/回滚语义。

例如,Enterprise Java Beans 和 Microsoft Transaction Server 支持分布式事务。

如果“外部调用”不是针对数据库,它会变得更加棘手。您可以尝试模拟事务,但有些事情很难回滚(文件系统操作)或不可能(将数据发布到服务器)。所以这将取决于具体的问题。

于 2009-10-23T04:03:09.250 回答
0

大多数 RDBMS 支持分布式事务。例如,MS SQL Server 使用分布式事务协调器 (DTC) 服务来征集分布式事务

于 2009-10-23T04:03:12.480 回答