访问事务以提交或回滚的首选方法是什么?

时间:2011-03-07 15:06:45

标签: php sql oracle transactions oci8

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

我有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连接的包装器,提交是oci_commit;回滚是oci_rollback

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

有没有更好的方法来处理交易?

2 个答案:

答案 0 :(得分:2)

  

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

我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();
}

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

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

答案 1 :(得分:1)

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

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

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