【问题标题】:How to manage nested database transactions in PHP?如何在 PHP 中管理嵌套的数据库事务?
【发布时间】:2014-11-27 14:56:41
【问题描述】:

我有一个方法 deleteUser(..) 执行一个 mysql 查询并调用另一个方法 logAction(..) 调用另一个 mysql 查询。

在这些方法中处理事务的最佳方式是什么?

示例伪代码:

function deleteUser($userId) {
    $db->execute('BEGIN TRANSACTION');

    $userCount = $db->execute("DELETE FROM users WHERE id=$userId");

    logAction('USER DELETED');

    $db->execute('INSERT INTO ... another action');

    $db->execute('COMMIT');
}

function logAction($action) {
    $db->execute('BEGIN TRANSACTION');

    $db->execute('INSERT INTO logtable ... ACTION');
    if (error) { 
        $db->execute('ROLLBACK');
    }

    $db->execute('COMMIT');
}

如您所见,我从 deleteUser() 方法调用 logAction,并遇到了两次“BEGIN TRANSACTION”。在 deleteUser() 完成之前,方法 logAction() 过早地调用了“COMMIT”。

有没有办法在这种嵌套方法中管理事务?

【问题讨论】:

    标签: php mysql transactions


    【解决方案1】:

    MySql 不支持嵌套事务。还有

    开始一个事务会导致提交任何待处理的事务

    http://dev.mysql.com/doc/refman/5.5/en/commit.html

    但是您需要在一个事务中执行这些查询或单独执行它们。你坚持在事务中运行你的方法。

    function deleteUser($userId) {
        if ($this->notInTransation()) throw new NotInTransactionException('not in transaction');
    
        $userCount = $db->execute("DELETE FROM users WHERE id=$userId");
    
        logAction('USER DELETED');
    
        $db->execute('INSERT INTO ... another action');
    
    }
    
    function logAction($action) {
        if ($this->notInTransation()) throw new NotInTransactionException('not in transaction');
        $db->execute('INSERT INTO logtable ... ACTION');
    }
    

    这样可以确保您的查询在一个事务中运行。使用这种方法,您应该将 begin、rollback、commit 放在更高的层次结构中,或者将查询放在更低的位置。

    附:您可以使用autocommit 变量来检查正在启动的事务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-10
      • 2022-01-19
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      • 2016-07-21
      • 1970-01-01
      相关资源
      最近更新 更多