繁体   English   中英

回滚MySQL查询

[英]Rolling back MySQL queries

如果我在基于IF的结构上有多个查询链,例如:

$query1 = mysqli_query("query here");

if(!query1){
    //display error
} else {
    $query2 = mysqli_query("another query here");
    if(!query2){
        //display error
        //rollback the query1
    } else {
        query3 = mysqli_query("yet again another query");
        if(!query3) {
            //display error
            //rollback the query2
            //rollback the query1
        } else {
            query4 = mysqli_query("eh.. another one");
            if(!query4){
                //display error
                //rollback the query3
                //rollback the query2
                //rollback the query1
            } else {
                return success;
            }
        }
    }
}

如果下一个查询失败,是否有最佳方式回滚上一个查询? 否则,我将使前2个查询成功完成,从而编辑了数据库,但是3°失败,因此3°和4°没有编辑dabatase,导致其损坏。

我想到了类似的东西:

    ...
    $query2 = mysqli_query("another query here");
    if(!query2){
        //display error
        $rollback = mysqli_query("query to rollback query1");
    } else {
        query3 = mysqli_query("yet again another query");
        if(!query3) {
            //display error
            $rollback = mysqli_query("query to rollback query2");
            $rollback = mysqli_query("query to rollback query1");
        } else {
        ...

但是以上方法赋予更多机会使更多查询失败。 还有其他更有效的方法吗?

这就是我将如何使用mysqli做到这一点:

配置mysqli(在应用程序的开头),以在查询失败时引发异常。

mysqli_report(MYSQLI_REPORT_STRICT);

这样,您将不需要所有if .. elseif .. else

$connection->begin_transaction();
try {
    $result1 = $connection->query("query 1");
    // do something with $result1

    $result2 = $connection->query("query 2");
    // do something with $result2

    $result3 = $connection->query("query 3");
    // do something with $result3

    // you will not get here if any of the queries fails
    $connection->commit();
} catch (Exception $e) {
    // if any of the queries fails, the following code will be executed
    $connection->rollback(); // roll back everything to the point of begin_transaction()
    // do other stuff to handle the error
}

更新

通常用户不关心,为什么他的操作失败。 如果查询失败,那绝不是用户的错。 这是开发人员或环境的错。 因此,没有理由根据哪个查询失败来呈现错误消息。

请注意,如果用户输入是失败查询的来源,则

  1. 您没有正确验证输入
  2. 您的查询不是注入安全的(如果输入可能导致SQL错误,也可以用来危害您的数据库。)

但是-我不是说没有理由-我只是一无所知。 因此,如果您希望错误消息取决于哪个查询失败,则可以执行以下操作:

$error = null;
$connection->begin_transaction();
try {
    try {
        $result1 = $connection->query("query 1");
    } catch (Exception $e) {
        $error = 'query 1 failed';
        throw $e;
    }
    // do something with $result1

    try {
        $result2 = $connection->query("query 2");
    } catch (Exception $e) {
        $error = 'query 2 failed';
        throw $e;
    }
    // do something with $result2

    // execute more queries the same way

    $connection->commit();
} catch (Exception $e) {
    $connection->rollback();
    // use $error to find out which query failed
    // do other stuff to handle the error
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM