Несколько слоев обслуживания и транзакции базы данных

Мне просто интересно, как лучше обрабатывать транзакции через несколько уровней обслуживания. Уровни службы используют ORM для хранения и извлечения из базы данных. Должны ли транзакции быть известны и обрабатываться в пределах отдельных слоев обслуживания? Или они должны обрабатываться другим слоем?

Например: у меня есть два уровня обслуживания для пользователей и клиентов. Я бы хотел:

1) Создайте и сохраните нового клиента
2) Создайте и сохраните нового пользователя
3) Назначить пользователя клиенту

Все в рамках одной транзакции.

Простой пример может выглядеть так:

$userManagementService = new UserManagementService; $newUserData = array(...); $newUser = $userManagementService->create($newUserData); $clientManagementService = new ClientManagementService; $newClientData = array(...); $newClient = $clientManagementService->create($newClientData); $userManagementService->assignUserToClient($newUser, $newClient); 

Где должна идти логика транзакций?

Не пытайтесь делать вложенные транзакции в пределах уровней обслуживания или внутри ORM.

Транзакции являются глобальными для соединения с БД. Если ваша RDBMS не поддерживает вложенные транзакции изначально, а ваш DB API предоставляет вложенные транзакции, вы можете столкнуться с аномалиями.

Подробнее см. В моем ответе « Как обнаружить, что транзакция уже запущена?

Поскольку вы используете PHP, объем транзакций не более одного запроса. Поэтому вам следует просто использовать транзакции, управляемые контейнером, а не транзакцию уровня сервиса. То есть, начните транзакцию в начале обработки запроса и совершите (или откат) по мере завершения обработки запроса.

Если исключение, требующее откат, происходит глубоко внутри вложенных действий ORM, тогда пузырь, что с помощью исключения, и пусть контейнер (т. Е. Ваш контроллер действия PHP) позаботится об этом.

Вы сталкиваетесь с агрегированием транзакций? Подходит ли этот псевдокод к тому, что я думаю, что вы говорите?

 try begin application transaction begin ORM transaction 1 create new user commit request begin ORM transaction 2 create new client commit request begin ORM transaction 3 create user client association commit request commit application tx catch() abort ORM tx 3 abort ORM tx 2 abort ORM tx 1 abort app tx 

В любом случае откат вложенной транзакции скорее всего вызовет исключение, и эти исключения будут логически откатывать все вложенные транзакции в двухфазной фиксации .

Возможно, я не получу то, что тебе нужно.