需要有关涉及PDO事务的嵌套原子操作的帮助

Sha*_*obe 5 php pdo

我有两个可以独立使用的不同模块,但Module2依赖于Module1.

Module2有一个需要原子的操作,它调用Module1中也需要是原子的操作.

假设我已经设置PDO :: ATTR_ERRMODE到PDO:ERRMODE_EXCEPTION,以下严重genericised和剪断代码可以产生这样的:PHP的致命错误:有消息"已经有一个活跃的交易"未捕获的异常"PDOException"

模块1:

<?php
class Module1
{
    ...
    public function atomicOperation($stuff)
    {
        $this->pdo->beginTransaction();
        try {
            $stmt = $this->pdo->prepare(...);
            ...
            $this->pdo->commit();
        }
        catch (Exception $ex) {
            $this->pdo->rollBack();
            throw $ex;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

模块2:

<?php
class Module2
{
    public $module1;
    ...
    public function atomicOperation($stuff)
    {
        $this->pdo->beginTransaction();
        try {
            $stmt = $this->pdo->prepare(...);
            ...
            $this->module1->atomicOperation($stuff);
            ...
            $this->pdo->commit();
        }
        catch (Exception $ex) {
            $this->pdo->rollBack();
            throw $ex;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定最好的方法 - 嵌套操作肯定会被独立调用,并且在自己调用时绝对必须是原子的.将onus放在类'user上以管理事务并保持原子性是不可取的,因为我确信该类的用户永远不会强制执行它.

Ark*_*rkh 4

您需要创建自己的类来扩展 PDO 并管理事务。就像是 :

<?php
class Db extends PDO{
  private $_inTrans = false;

  public function beginTransaction(){
    if(!$this->_inTrans){
      $this->_inTrans = parent::beginTransaction();
    }
    return $this->_inTrans;
  }

  public function commit(){
    if($this->_inTrans){
      $this->_inTrans = false;
      return parent::commit();
    }
    return true;
  }

  public function rollBack(){
    if($this->_inTrans){
      $this->_inTrans = false;
      return parent::rollBack();
    }
    return true;
  }

  public function transactionStarted(){
    return $this->_inTrans;
  }

}
Run Code Online (Sandbox Code Playgroud)

您仍然需要检查传递的所有查询,以防某些事务在那里启动。

模块 1:

<?php
class Module1
{
    ...
    public function atomicOperation($stuff)
    {
        $transactionAlreadyStarted = $this->pdo->transactionStarted();
        if(!$transactionAlreadyStarted){
            $this->pdo->beginTransaction();
        }
        try {
            $stmt = $this->pdo->prepare(...);
            ...

            if(!$transactionAlreadyStarted && $this->pdo->transactionStarted()){
                $this->pdo->commit();
            }
        }
        catch (Exception $ex) {
            if($this->pdo->transactionStarted()){
                $this->pdo->rollBack();
            }
            throw $ex;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

模块 2:

<?php
class Module2
{
    public $module1;
    ...
    public function atomicOperation($stuff)
    {
        $transactionAlreadyStarted = $this->pdo->transactionStarted();
        if(!$transactionAlreadyStarted){
            $this->pdo->beginTransaction();
        }
        try {
            $stmt = $this->pdo->prepare(...);
            ...
            $this->module1->atomicOperation($stuff);
            ...
            if(!$transactionAlreadyStarted && $this->pdo->transactionStarted()){
                $this->pdo->commit();
            }
        }
        catch (Exception $ex) {
            if($this->pdo->transactionStarted()){
                $this->pdo->rollBack();
            }
            throw $ex;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)