【问题标题】:What is the preferred way to get access a transaction to commit or rollback?访问事务以提交或回滚的首选方法是什么?
【发布时间】:2011-03-07 15:06:44
【问题描述】:

我了解事务是如何工作的,并且一切都按预期运行,但我不喜欢我访问连接以提交或回滚事务的方式。

我有 3 个服务类可以访问同一个单例连接对象。我想将这三件事包装在一个事务中,所以我这样做:

try {
  $service1 = new ServiceOne;
  $service2 = new ServiceTwo;
  $service3 = new ServiceThree;

  $service1->insertRec1($data);
  $service2->deleteRec2($data);
  $service3->updateRec3($data);

  $service1->getSingletonConnection()->commit();
}
catch(Exception $ex) {
  $service1->getSingletonConnection()->rollback();
}

getSingletonConnection返回的连接对象只是oci8连接的一个包装器,committing是oci_commit;回滚是oci_rollback

正如我所说,这是可行的,因为它们都在访问同一个连接,但是通过任意服务对象访问连接感觉是错误的。此外,我的应用程序中使用了两个不同的数据库,因此我需要确保检索并提交正确的数据库......但不确定是否有任何解决方法。

有没有更好的交易处理方式?

【问题讨论】:

    标签: php sql oracle transactions oci8


    【解决方案1】:

    访问感觉不对 通过任意连接 服务对象。

    我 100% 同意。

    在我看来,如果每个服务只构成数据库事务的一部分,那么服务就不能直接负责确定要使用的数据库会话。您应该在定义事务的代码级别选择和管理连接。

    因此您当前的代码将被修改为:

    try {
      $conn = getSingletonConnection();
      $service1 = new ServiceOne($conn);
      $service2 = new ServiceTwo($conn);
      $service3 = new ServiceThree($conn);
    
      $service1->insertRec1($data);
      $service2->deleteRec2($data);
      $service3->updateRec3($data);
    
      $conn->commit();
    }
    catch(Exception $ex) {
      $conn->rollback();
    }
    

    这似乎会简化您的双数据库问题的处理,因为只有一个地方可以决定使用哪个连接,并且您将直接引用该连接直到您结束事务。

    如果您想从单例连接扩展到连接池,这是我能想到的唯一保证所有三个服务调用使用相同连接的方法。

    【讨论】:

    • 我完全同意,不过,如果你还是要传入对象,你甚至可能要考虑完全取消“Singleton”实现。
    【解决方案2】:

    单一连接本质上没有任何问题。 如果您有多个连接,则每个连接都运行一个独立的事务。你基本上有两种选择。

    • 保持当前单曲 每个连接对象 三项服务
    • 保持独立 连接(有相关的开销) 对于每个服务,以及提交/回滚 每个单独的连接单独 (不是特别安全,因为你 不能保证 ACID 的一致性 然后)

    作为一种绕过您要连接到的两个独立数据库实例的方法:使用 db 链接以便您只连接到单个数据库

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-02
      相关资源
      最近更新 更多