php - 每个语句 VS 的 PDO 异常。一次交易?

标签 php exception pdo

我即将在我的 php 脚本中实现事务,我正在做一些测试以帮助我自己准确地理解它们是如何工作的。我有以下代码片段:

try{
    $db->beginTransaction();

    $update = "UPDATE persons SET first_name = 'Adam' WHERE person_id = 4";
    $stmt = $db->exec($update);


    $select = "SELECT person_id, column_that_doesnt_exist FROM persons";

    try{
        $stmt = $db->prepare($select);
        $stmt->execute();
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        echo json_encode('success');
    } catch (PDOException $e) {
        echo 'execute failure';
    }

    echo ' code gets here';

    $db->commit();
} catch(PDOException $e){
    $db->rollBack();
    echo json_encode('commit failure');
}

哪些输出:

execute failure code gets here

第 4 个人的名字更新为 Adam。

现在我很确定它正在提交,因为第二个查询实际上从未失败过,因为自 prepare 以来它从未真正执行过是失败点。

如果 PDOException 就好了最后被抛出catch因为一个被扔进了“内部”try但我可以解决这个问题。

现在如果我取出“内部”try并有这个代码:

try{
        $db->beginTransaction();

        $update = "UPDATE persons SET first_name = 'Adam' WHERE person_id = 4";
        $stmt = $db->exec($update);


        $select = "SELECT person_id, column_that_doesnt_exist FROM persons";


            $stmt = $db->prepare($select);
            $stmt->execute();
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);


        $db->commit();
    } catch(PDOException $e){
        $db->rollBack();
        echo json_encode('commit failure');
    }

提交失败,数据库回滚并输出commit failure正如预期的那样。

因此在生产中,我是否应该将每个单独的语句包装在 try-catch 中? ,而是将我所有的陈述都放在一个大的 try 中 block (事务),然后捕获 commit最后异常(exception)?这对我来说似乎不正确....并且同样不会给你太多关于哪个语句失败的信息......

最佳答案

您使用内部 try..catch block 捕获异常,而不重新抛出它。这意味着该异常已得到处理,并且代码继续进行,就好像没有出错一样,提交事务。

通常这不是理想的解决方案,因为事务主要用于使多个数据修改语句的组合成为原子。通过使用事务,您可以在一切顺利时提交所有内容,或者在出现问题时回滚所有内容。

此外,由于在启动事务本身失败时没有要提交或回滚的内容,因此您应该将其从异常处理中删除。所以正确的结构应该是:

StartTransaction;
try {
  ModifyData;
  CommitTransaction;
}
catch {
  RollbackTransaction;
  // Log/mail/show/ignore error
}

如果你想继续插入记录,即使插入其中一条记录失败,你也不需要事务。

如果您想获取有关哪个项目失败的具体信息,您可以重新抛出异常或抛出一个新异常:

StartTransaction;
try {

  foreach ($persons as $person) {
    try {
      ModifyPerson($person);
    }
    catch {
      throw new Exception("Updating person {$person->name} failed");
    }
  }

  CommitTransaction;
}
catch {
  RollbackTransaction;
  // Log/mail/show/ignore error
}

通过(重新)从内部异常处理程序抛出异常,您可以直接跳转到外部异常处理程序,终止循环并绕过提交。

关于php - 每个语句 VS 的 PDO 异常。一次交易?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22946952/

相关文章:

php - Laravel 调用未定义的方法 Config::get()

java - 返回 Try 的方法是否允许抛出异常?

php - 如何通过PDO正确获取以表的主键作为数组键的数组?

mysql - 使用 Ajax-PDO 的 cleditor 内容不会保存或删除

php - 使用Codeigniter将视频远程上传到youtube

php - 左加入 Doctrine 查询语言

php - 使用结果缓存和不使用结果缓存来计时我的 php 函数

java - serversocket.accept()何时会引发异常? [java]

c# - 使用空分配修复 'Use of unassigned local variable'。为什么?

php - 如果我希望它接受带有 PDO 的 INT 和 NULL,如何绑定(bind)一个值?