Symfony 原则:如何防止交易变成';仅回滚';通过捕获异常?

Symfony 原则:如何防止交易变成';仅回滚';通过捕获异常?,symfony,exception,transactions,doctrine,Symfony,Exception,Transactions,Doctrine,由于postRemove事件处理程序中出现异常,删除实体失败。即使捕获到异常,删除也会失败,因为无法再提交事务如何解决这个问题? 完整故事: 我需要使用原则跟踪基于Symfony 3.4的web服务中删除的一些实体 为此,我创建了一个EventSubscriber,它处理postRemove事件,以检查是否需要记录删除的实体。在这种情况下,实体UUID存储在th DB的DeleteLog表中 这很好,但在极少数情况下,DeleteLogEntry的持久化会失败,因为给定UUID已经存在一个需要唯

由于
postRemove
事件处理程序中出现异常,删除实体失败。即使捕获到异常,删除也会失败,因为无法再提交事务如何解决这个问题?

完整故事:

我需要使用
原则
跟踪基于
Symfony 3.4
的web服务中删除的一些实体

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

这很好,但在极少数情况下,
DeleteLogEntry
的持久化会失败,因为给定UUID已经存在一个需要唯一的日志条目

这个问题的根源是一些我无法改变自己的第三方代码。作为临时解决方案,尝试捕获
UniqueConstraintViolationException
。这并不能解决问题,因为现在我得到了
ConnectionException

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

有可能解决这个难题吗?

当然,在创建新的UUID之前,我可以检查具有给定UUID的
DeleteLogEntry
。但由于这一问题只在极少数情况下发生,因此大多数情况下检查结果都是否定的。当然,无论如何运行检查都不会对性能造成灾难性影响,但似乎并不是最好的解决方案


是否可以捕获异常并防止事务被标记为仅回滚?

不,不可能防止事务被标记。

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

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

其他可能的解决办法:

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