原则:如何通过捕获的异常来防止事务变为“仅回滚”?

时间:2019-01-24 14:08:55

标签: symfony exception transactions doctrine

由于<html> <head> <title>The Materialize Selects Example</title> <meta name="viewport" content="width = device-width, initial-scale = 1"> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.3/css/materialize.min.css"> <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.3/js/materialize.min.js"> </script> <script> $(document).ready(function() { $('select').material_select(); }); </script> </head> <body class="container"> <div class="row"> <form class="col s12"> <div class="row"> <label>Materialize Select</label> <select> <option value="" disabled selected>Select Fruit</option> <option value="1">Mango</option> <option value="2">Orange</option> <option value="3">Apple</option> </select> </div> <div class="row"> <label>Materialize Multi Select</label> <select multiple> <option value="" disabled selected>Select Fruit</option> <option value="1">Mango</option> <option value="2">Orange</option> <option value="3">Apple</option> </select> </div> <div class="row"> <label>Select with Optgroup</label> <select> <optgroup label="Fruits"> <option value="1">Mango</option> <option value="2">Orange</option> <option value="3">Apple</option> </optgroup> <optgroup label="Vegs"> <option value="4">Brinjal</option> <option value="5">Potato</option> <option value="6">Tomato</option> </optgroup> </select> </div> <div class="row"> <label>Select with images</label> <select class="icons"> <option value="" disabled selected>Select Technology</option> <option value="1" data-icon="/html5/images/html5-mini-logo.jpg" class="circle"> HTML</option> <option value="2">JavaScript</option> <option value="3">CSS</option> </select> </div> <div class="row"> <label>Browser default Select</label> <select class="browser-default"> <option value="" disabled selected>Select Fruit</option> <option value="1">Mango</option> <option value="2">Orange</option> <option value="3">Apple</option> </select> </div> <div class="row"> <label>Disabled Materialize Select</label> <label>Disabled Materialize Select</label> <select disabled> <option value="" disabled selected>Select Fruit</option> <option value="1">Mango</option> <option value="2">Orange</option> <option value="3">Apple</option> </select> </div> <div class="row"> <label>Disabled Browser default Select</label> <select class="browser-default" disabled> <option value="" disabled selected>Select Fruit</option> <option value="1">Mango</option> <option value="2">Orange</option> <option value="3">Apple</option> </select> </div> </form> </div> </body> </html>事件处理程序中的异常,删除实体失败。即使捕获到异常,删除也将失败,因为无法再提交事务。 该如何解决?

完整故事:

我需要使用postRemove跟踪基于Symfony 3.4的Web服务中的某些已删除实体。

为此,我创建了一个Doctrine处理该EventSubscriber事件,以检查是否需要记录已删除的实体。在这种情况下,实体UUID存储在数据库的postRemove表中。

这很好,但是在极少数情况下,DeleteLog的持久化失败,因为给定UUID已经存在一个日志条目,该条目必须是唯一的。

此问题的根源是一些我无法更改自己的第三方代码。作为一种临时解决方案,尝试捕获DeleteLogEntry。由于我现在得到UniqueConstraintViolationException

,因此无法解决问题
  

事务提交失败,因为已将事务标记为   仅回滚。

是否可以解决这个难题?

当然,我可以在创建新UUID之前检查是否存在具有给定UUID的ConnectionException。但是由于此问题仅在极少数情况下发生,所以大多数情况下检查都是负面的。当然,运行检查不会对性能造成灾难性的影响,但似乎并不是最佳解决方案。

是否有可能捕获异常并防止仅将事务标记为回滚?

1 个答案:

答案 0 :(得分:1)

否,无法阻止交易被标记。

Doctine为postRemove启动nested transaction,如果失败,则不应提交任何其他事务。在这种情况下,将事务标记为仅回滚(甚至关闭实体管理器)是预期的行为,因为Doctrine没有其他方法可以确保一致性,因为不支持真正的嵌套事务。

如果性能不是问题,那么检查DeleteLogEntry是个不错的选择。

其他可能的解决方法:

  • 将ID暂时存储在某个地方(Redis,Memcache,文件等),并在提交初始删除后稍后更新DeleteLogEntry
  • 使用单独的实体管理器/连接来更新DeleteLogEntry
  • 删除唯一约束并使用后台任务来监视重复项