如何在PHP中管理嵌套数据库事务?

时间:2014-11-27 14:56:41

标签: php mysql transactions

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

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

伪代码示例:

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'两次。方法logAction()调用' COMMIT'在deleteUser()完成之前过早。

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

1 个答案:

答案 0 :(得分: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更高层次化,或者将查询放低。

P.S。您可以使用autocommit变量来检查正在启动的事务。