место транзакций в архитектуре

grigori

( ͡° ͜ʖ ͡°)
Команда форума
привет всем!
есть у нас такое большое приложение, которое пишет команда численностью >5 человек,
в нем есть контроллеры, классы ActiveRecord для маппинга таблиц, сервисный слой модели с запросами к разным таблицам и к другим методам сервисного слоя,

вопрос: куда писать управление транзакциями? в контроллер как-то неправильно,
а в сервисном слое опасно, т.к. модель в транзакции может вызывать другую модель
mysql при начале вложенной транзакции коммитит предыдущую, а я бы не хотел чтобы транзакция закоммитилась раньше времени

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

С.

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

В веб-приложниях так или иначе приходится различать процедуру, дернутую по инициативе HTML запроса (action) от процедуры вызваной внутренними модулями (routine).
 

флоппик

promotor fidei
Команда форума
Партнер клуба
По моему мнению в модели. Но наверное неправильно, когда "модель может вызывать другую модель"
Скорее, если атомарная операция (транзакция) включает в себя несколько таблиц, она должна быть реализована одной моделью? (AR != Модель, да)
 

podbeltsev

Новичок
Или добавить счетчик в классе для работы с БД

startTransaction (с++)
commitTransaction (c--, при нулевом commit в базу)
rollbackTransaction (c=0, rollback в базу, вызываться будет в случае ошибки в исключениях)
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
получается, что счетчик на уровне объекта соединения - оптимальное решение,
в общем, решим на уровне фреймворка

Unit of Work - надо продумать как перестроить под это приложение и yii, в 2ке-то они уже делают это, но где та 2ка
 

Тугай

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

В mysql, нет SAVE POINT, нет вложенных транзакций, через флаг будет хак костыль, но тут и нет вариантов.
Так что плюсую за "счетчик на уровне объекта соединения - оптимальное решение".
 

Тугай

Новичок
Раз есть то тогда надо и реализовать вложенные транзакции :) И счетчик нафик, вреней из него надо сделать SAVE POINT'ы.

Меня с толку сбили коменты про PDO в котрых это счетчик предлагают.

В ADO, RDO от microsofta, автоматом работает вложеность.
 

С.

Продвинутый новичок
По мне это выглядит как оверинжиниринг. А надо просто олдскульно оформить в процедуры только повторяюшиеся куски кода (в которые открытие-закрытие транзакции не входят).
 

Redjik

Джедай-мастер
Раз есть то тогда надо и реализовать вложенные транзакции :) И счетчик нафик, вреней из него надо сделать SAVE POINT'ы.
Ага так и думаю сделать, только вложенность деревьями, а счетчик только для идентификатора сейвпоинта.
 

Yoskaldyr

"Спамер"
Партнер клуба
Насчет проблемы коммита при вложенных транзакциях.
Можно реализовать через чекпоинты если транзакция вложенная. И роллбеки делать на предыдущие чекпоинты или полный роллбек например в случае критических ошибок.
 

WMix

герр M:)ller
Партнер клуба
я если чесно вообще не понимаю смысла вложеных трансакций, кроме чтоб ресурсы освободить...
 

Redjik

Джедай-мастер
WMix
а все очень просто - есть корзина, есть юзер, есть адреса юзеров, и есть заказ ... и примерно 6 комбинаций регистрации заказа из того, что я перечислил
 

WMix

герр M:)ller
Партнер клуба
Код:
начало трансакции
... 
начало трансакции
... // корзина
коммит
начало трансакции
... // юзер
рольбак
...
коммит
и ничего не выполнилось (вернее я не хотел бы чтоб выполнялось), в чем смысл вложеных трансакций?

соглашусь что в консоли это удобно

4! = 4*3*2*1 = 24 комбинаций регистрации заказ
 

Тугай

Новичок
WMix
Нагуглил, http://msdn.microsoft.com/en-us/library/ms178157(v=sql.105).aspx написано для чего SAVE POINT.

На стороне клиента, запомнилось из документации по ODBC и RDO объединяйте вызовы в транзакции, т.е. в блоки BeginTrans и Commit опять же для производительности.
Для умного драйвера бд - это дополнительная информация для кеширования оптимизации запросов. Например, несколько подряд идущих INSERT UPDATE, можо не посылать до заветного commit.

Похоже что в PDO нет реализации вложенных транзакций, потому что SAVE POINT, это совсем не то или очень мало.
 

Ragazzo

TDD interested
podbeltsev
я посмотрю как ты UoW будешь для query-builder использовать :)
grigori
Unit of Work - надо продумать как перестроить под это приложение и yii, в 2ке-то они уже делают это, но где та 2ка
в 2ке его нет :) там лишь дёртиаттрибутс, похоже но не то :)
в postgresql нет вложенных транзакций :S
вопрос: куда писать управление транзакциями? в контроллер как-то неправильно,
а в сервисном слое опасно, т.к. модель в транзакции может вызывать другую модель
я просто проверяю не была начата уже транзакция, если нет, то создаю. прекрасно работает :)
 

Redjik

Джедай-мастер
Все - разобрался наконец - совмещу два подхода.

Один - частичное сохранение данных (что дает класс по ссылке grigori) ($partialSave = true)
эмуляция логики http://docs.oracle.com/cd/E17076_02/html/gsg_txn/JAVA/nestedtxn.html

Второй - полный rollback всех изменений не зависимо от ($partialSave = false), чтобы сохранить "атомарность операции"(с)
 
Сверху