4

Мне просто интересно, как лучше всего обрабатывать транзакции через несколько слоев обслуживания. Уровни службы используют 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); 

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

ответ

2

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

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

Для получения дополнительной информации см мой ответ на How do detect that transaction has already been started?

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

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

+0

Gotcha, имеет смысл. Спасибо за ссылку, а также хорошие объяснения там. –

1

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

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 

В любой момент откат вложенной транзакции, скорее всего, бросить исключение, и эти исключения логически откатить все вложенные транзакции в two-phase commit.

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

Смежные вопросы