php – 每个语句的PDO异常VS.一次交易?
我即将在我的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 } 通过(重新)从内部异常处理程序抛出异常,您直接跳转到外部异常处理程序,终止循环,并绕过提交. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |