Всъщност това е точно как вложените транзакции е проектиран за. Цитирам от документи на Oracle:
И така, дъщерна транзакция в обикновенавложена транзакция няма дума за това как той или другите деца или родител (по-голяма транзакция ) може да се държи, различно от промяната на взаимните данни или неуспех за изключение.
Но можете да му предоставите (детска транзакция ) много ограничен шанс за гласуване на неговата съдба чрез използване на sub-transaction
функция, както е посочено в rails docs
чрез подаване на requires_new: true
User.transaction do
User.create(username: 'Kotori')
User.transaction(requires_new: true) do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback
end
end
Което както казват документите:създава само „Котори“. тъй като мощното дете „Нему“ избра да умре тихо.
Повече подробности за правила за вложени транзакции (документи на oracle )
Актуализация:
За да разберете по-добре защо релсите nested transactions
работи по този начин, трябва да знаете малко повече за това как работят вложените транзакции на ниво DB, цитирам от rails api документи
:
Добре, тогава документите описват поведението на nested transaction
в двата споменати случая, както следва:
В случай на вложено повикване, #transaction ще се държи по следния начин:
-
Блокът ще бъде стартиран, без да се прави нищо. Всички изрази на базата данни, които се случват в блока, ефективно се добавят към вече отворената транзакция на база данни.
-
Въпреки това, ако :requires_new е зададено, блокът ще бъде обвит в точка за запис на база данни, действаща като подтранзакция.
Представям си внимателен, само си представете това:
опция (1) (без requires_new) има ли в случай, че сте използвали СУБД, която напълно поддържа nested transactions
или сте доволни от "фалшивото" поведение на nested_attributes
докато опция(2) е да поддържа savepoint
заобиколно решение, ако не го направите.