Доктрина: как предотвратить превращение транзакции в «только откат» из-за перехваченного исключения?

Удаление объекта завершается ошибкой из-за исключения в обработчике событий postRemove. Даже если исключение перехвачено, удаление завершается ошибкой, поскольку транзакция больше не может быть зафиксирована. Как это решить?

Полная история:

Мне нужно отслеживать некоторые удаленные объекты в веб-службе на основе Symfony 3.4, используя Doctrine.

Для этого я создал EventSubscriber, который обрабатывает событие postRemove, чтобы проверить, нужно ли регистрировать удаленный объект. В этом случае UUID объектов хранится в таблице DeleteLog th DB.

Это работает нормально, но в редких случаях сохранение DeleteLogEntry не удается, поскольку уже существует запись в журнале для данного UUID, которая должна быть уникальной.

Источником этой проблемы является какой-то сторонний код, который я не могу изменить сам. Как временное решение попробовал поймать UniqueConstraintViolationException. Это не решает проблему, так как теперь я получаю ConnectionException.

Transaction commit failed because the transaction has been marked for rollback only.

Можно ли решить эту дилемму?

Конечно, я мог бы проверить, существует ли DeleteLogEntry с данным UUID, прежде чем создавать новый. Но поскольку эта проблема возникает только в редких случаях, в большинстве случаев проверка будет отрицательной. Конечно, выполнение проверки в любом случае не оказывает катастрофического влияния на производительность, но просто кажется не лучшим решением.

Есть ли возможность поймать исключение и предотвратить пометку транзакции только как откат?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
2
0
5 411
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет, невозможно предотвратить пометку транзакции.

Doctine запускает вложенная транзакция для postRemove, и если это не удается, никакие другие транзакции не должны совершаться. Пометка транзакции только для отката (и даже закрытие диспетчера сущностей) является ожидаемым поведением в таком сценарии, потому что у Doctrine нет другого способа обеспечить согласованность, поскольку нет поддержки реальных вложенных транзакций.

Если производительность не является проблемой, хорошим вариантом будет проверка DeleteLogEntry.

Другие возможные обходные пути:

  • временно сохраните идентификатор где-нибудь (Redis, Memcache, файл и т. д.) и обновите DeleteLogEntry позже, после первоначального удаления.
  • используйте отдельный менеджер объектов/соединение для обновления DeleteLogEntry
  • удалите уникальное ограничение и используйте фоновую задачу для поиска дубликатов

Другие вопросы по теме