Здесь много вопросов, так что давайте рассмотрим их шаг за шагом.
Прежде чем мы начнем, вспомните, как Doctrine работает внутри: если сущность или набор сущностей запрашивается через запрос или репозиторий, Doctrine загружает данные сущности из базы данных, создает сущности, заполняет их данными, отслеживает изменения и синхронизирует изменения обратно в базу данных. У сущностей доктрины есть состояния , обычно они находятся в управляемом состоянии, если вы не отсоедините их. Когда вы очищаете менеджер сущностей, сущности становятся отсоединенными .
Теперь, чтобы ответить на ваши вопросы:
если DaemonA очищает сущности, а DaemonB еще не сбросил сохраненные изменения, что происходит?
Очистка менеджера сущностей означает только то, что сущности отсоединяются и, если на них больше нет ссылок, собираются в мусор (я думаю). На уровне базы данных это не имеет значения.
Когда DaemonA сбрасывает, влияет ли это каким-либо образом на объекты в DaemonB?
Да, но не во время работы DaemonB и не перезагружает сущности из базы данных. Если DaemonA изменяет сущности, а DaemonB изменяет те же сущности перед тем, как перезагружать их, модификации DaemonB сохраняются.
Могут ли некоторые быть продублированы?
Только если вы сохраните отсоединенные объекты (хотя у них будет новый идентификатор). Однако в любом случае сохранение отдельных объектов не имеет смысла.
Если так, что я могу сделать, чтобы избежать подобных вещей?
Замки и транзакции!
Каждая модификация вашей базы данных, которая содержит более одного запроса, должна быть включена в транзакцию. Это позволяет избежать несоответствий, если что-то идет не так или если параллельный запрос изменяет данные. На уровне PHP транзакция снова должна быть заключена в блок try / catch.
Если вы изменяете сущность, заблокируйте ее. Доктрина поддерживает различные виды блокировки ; выберите тот, который подходит вашему сценарию лучше всего.
Код в одном из ваших демонов может выглядеть следующим образом:
try
{
$em->beginTransaction();
$entity = $em->find($entityClassName, $id);
// lock the entity for all reading and writing.
$em->lock($entity, LockMode::PESSIMISTIC_WRITE);
$em->flush();
$em->commit();
}
catch (Exception $e)
{
$em->rollback();
throw $e;
}
Обратите внимание, что в зависимости от вашей стратегии блокировки и общей реализации вашей системы, демоны могут блокировать друг друга, блокируя базу данных до того момента, когда в вашей системе не хватит ресурсов.
Например, пессимистическая блокировка записи более безопасна (она гарантирует, что другие процессы не читают данные до завершения модификации), но другие процессы должны будут ждать, пока не будет снята блокировка.
Будьте внимательны и проводите тестирование в условиях большой нагрузки!