【问题标题】:Transaction troubleshooting事务疑难解答
【发布时间】:2014-08-29 18:31:33
【问题描述】:

我正在通过 JavaScript 从前端表单收集数据并将其传递给我的 PHP 脚本以保存到数据库。三个表必须要么全部填满,要么都不填(有错误)。我有以下文本墙作为我当前的脚本(为了便于阅读而大大缩写),我认为它可以工作,但我知道不能 - 列名拼写错误,应该会引发错误,但没有,并且保存了另外两个表。

谁能指出我哪里出错了?

    //SAVE TO DB
    $conn -> beginTransaction();
    $errors = array();


    //record edit
    foreach($edits as $edit)
    {
        try
        {
            $q = $conn  -> prepare(" INSERT INTO edits ( col1, col2 ) VALUES ( ?,? ) ");
            $q          -> execute( array( $a, $b ) );

        }
        catch(PDOException $e)
        {
            $conn->rollback();
            $errors['Edits'][] = $e->getMessage();
        }
    }

    //record action
    foreach($records as $id => $record)
    {
        if($haveExitingRecords)
        {
            //update existing record
            try
            {
                $q = $conn -> prepare(" UPDATE records SET col1 = ? WHERE ID = ? ");

                $q -> execute(array( $a, $b ));
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['Updates'][] = $e->getMessage();
            }
        }
        else
        {
            //insert new record
            try
            {
                $q = $conn -> prepare(" INSERT INTO records ( col1 ) VALUES ( ? ) ");

                $q -> execute( array( $a ) );
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['Inserts'][] = $e->getMessage();
            }
        }

        //also record where x...
        if($x !== 1)
        {
            try
            {
                //check for existing record
                $q = $conn  -> prepare(" SELECT ID FROM ifCases WHERE col1 = ? ");
                $q          -> execute( array( $a ) );
                $prev = $q  -> fetch(PDO::FETCH_COLUMN);

                if(!$prev)
                {
                    $q = $conn  -> prepare(" INSERT INTO ifCases ( col1, col2 ) VALUES ( ?, ? ) ");
                    $q          -> execute( array( $a, $b ) );
                }
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['ifCases'][] = $e->getMessage();
            }
        }
        else
        {
            try
            {
                //check for existing record
                $q = $conn  -> prepare(" SELECT ID FROM ifCases WHERE col1 = ? AND col2 = ? ");
                $q          -> execute(array( $a, $b ));
                $prev = $q  -> fetch(PDO::FETCH_COLUMN);

                if($prev > 0)
                {
                    try
                    {
                        //delete case
                        $q = $conn  -> prepare(" DELETE FROM ifCases WHERE  col1 = ? AND col2 = ? ");
                        $q          -> execute(array($ $a, $b ));
                    }
                    catch(PDOException $e)
                    {
                        $conn->rollback();
                        $errors['Delete ifCase'][] = $e->getMessage();
                    }
                }
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['ifCases'][] = $e->getMessage();
            }
        }
    }

    if(empty($errors))
    {
        $conn->commit();
        echo '{"success":"ok"}';
    }
    else
    {
        echo json_encode($errors);
    }

【问题讨论】:

  • 您在连接上设置了错误模式? $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

标签: php pdo transactions


【解决方案1】:

所以你捕获一个异常,回滚事务,到目前为止所做的任何工作都被撤消了。

但是仅仅因为你回滚,并不意味着你的脚本不能执行后续语句。它们只是隐式启动自己的新事务,如果您将 MySQL 的 autocommit 变量保留为默认条件,它们会自动提交。

当捕获到异常时,您应该将代码从当前函数更改为exitreturn。或者设置一个标志变量,如果设置了标志,则跳过后续的数据库操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多