Несколько уровней обслуживания и транзакции базы данных - PullRequest
4 голосов
/ 28 октября 2009

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

3 голосов
/ 05 ноября 2009

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

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

Подробнее см. Мой ответ на Как определить, что транзакция уже была начата?

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

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

1 голос
/ 01 ноября 2009

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

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

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

Я не могу получить то, что вы после этого.

...