【问题标题】:Active transactions and PHP活跃事务和 PHP
【发布时间】:2013-06-17 15:36:58
【问题描述】:

给定一个具有多个函数样式的 PHP 类

public function $op_Data() {
    $command = Yii::app()->db->createCommand("");
    $transaction = Yii::app->db->beginTransaction();

    try {
      //code here
      $transaction->commit()
    } catch (Exception $e) {
      $transaction->rollback();
      return "Operation Failed\n" . $e->getTraceAsString();
    }
}

提交操作成功或返回错误后,是否可以继续使用之前方法中的事务?

我的意思是,调用了一个插入函数。它检查事务是否处于活动状态,并使用它。如果一个事务不活跃,它会创建一个。对于需要事务功能的所有功能,都会进行相同的检查。

如果此功能存在,是否会影响特定功能内的提交/回滚操作?

【问题讨论】:

    标签: php yii transactions


    【解决方案1】:

    如果您想在单个事务中执行放置在不同方法中的 SQL 查询,您可以像这样包装它们:

    $transaction = Yii::app()->db->beginTransaction();
    try {
        $instance->insertMethod();
        $instance->updateMethod();
        $instance->deleteMethod();
        // ...more DB methods calls
        $transaction->commit();
    }
    catch (Exception $e) {
        $transaction->rollback();
    }
    

    但是,在这种情况下,您必须检查您的方法是否已经在外部创建了事务。可以使用CDbConnectiongetCurrentTransaction() 方法来完成,如下所示:

    public function $op_Data() {
        $command = Yii::app()->db->createCommand("");
        $transaction = Yii::app()->db->getCurrentTransaction();
        if ($transaction !== null) {
            // Transaction already started outside
            $transaction = null;
        }
        else {
            // There is no outer transaction, creating a local one
            $transaction = Yii::app()->db->beginTransaction();
        }
    
        try {
          //code here
          if ($transaction !== null)
              $transaction->commit()
        } catch (Exception $e) {
          if ($transaction !== null)
              $transaction->rollback();
          return "Operation Failed\n" . $e->getTraceAsString();
        }
    }
    

    更新

    如果保留现有 PHP 类的代码是首选方法,您还可以考虑覆盖 PHP 的 PDO 类的默认实现的机会。 This nested transactions implementation 是可能的解决方案的骨架。主要思想是在第一次调用beginTransaction() 时开始唯一的事务,并在第N 次调用commit()rollback() 时真正结束事务,其中N - 是连续beginTransaction() 调用的计数。

    【讨论】:

    • 如果事务之前已经提交或回滚,调用后续的提交/回滚将是徒劳的(没有开始)。
    • 您是对的,但上面提出的解决方法永远不会进行后续的commit()rollback() 调用。当在CDbTranscation 实例上调用commit()rollback() 时,其_active 状态将变为false,然后getCurrentTransaction() 返回null。这就是为什么 PHP 类的修改方法只有在没有任何其他事务启动时才会启动并提交/回滚自己的本地事务。在其他情况下,该方法本身不处理任何允许在外部进行的事务。
    • 用替代解决方案更新了答案。
    • 您的第一个解决方案是我在提出问题后基本上作为测试实施的。我对重用现有活动事务的担忧在于提交/回滚完整性。经过测试,我已经确认回滚了几个错误的提交没有问题。
    【解决方案2】:

    这在很大程度上取决于您的数据库引擎,但通常一旦事务被回滚或提交,您将不得不“创建”一个新的。

    事务是数据库引擎中的“保存点”,应该不会影响您的 php 代码。

    【讨论】:

      猜你喜欢
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      • 2013-11-12
      • 2013-02-27
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      相关资源
      最近更新 更多