加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 每个语句的PDO异常VS.一次交易?

发布时间:2020-12-13 22:52:14 所属栏目:PHP教程 来源:网络整理
导读:我即将在我的php脚本中实现事务,我正在做一些测试,以帮助自己准确理解它们是如何工作的.我有以下代码片段: try{ $db-beginTransaction(); $update = "UPDATE persons SET first_name = 'Adam' WHERE person_id = 4"; $stmt = $db-exec($update); $select =
我即将在我的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');
}

哪个输出:

执行失败代码到这里

并且第4个人的名字更新为Adam.

现在我很确定它已经被提交,因为第二个查询从未真正失败,因为它从未实际执行过,因为准备就是失败点.

如果为最后一次捕获抛出PDOException会很好,因为在“内部”尝试中抛出了一个,但我可以解决这个问题.

现在,如果我拿出“内部”尝试并拥有此代码:

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');
    }

提交失败,db回滚并按预期输出提交失败.

所以在生产中,我不应该将每个单独的语句包装在try-catch中,而是将所有语句都放在一个大的try块(事务)中,然后在最后捕获提交Exception?这对我来说似乎不对……同样也不会给你很多关于哪个陈述失败的信息….

解决方法

您可以使用内部try..catch块捕获异常,而无需重新抛出它.这意味着处理该异常,并且代码继续,好像什么都没有出错,提交事务.

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

此外,由于在启动事务本身失败时无需提交或回滚,因此您应该将其从异常处理中拉出来.所以适当的结构是:

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
}

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读