@ewgenkmz
Back-end programmer

Транзакции BD в Laravel. Какое поведение в различных ситуациях?

Один из способов использовать транзакции в Laravel:
DB::beginTransaction();
// великолепный полезный код
DB::commit();

Но вот интересно что произойдет:
1) Например, если код не дойдет до DB::commit();.
DB::beginTransaction();
// начало великолепного и полезного кода
Exeption или упаси бог Fatal Error где-то в процессе
//конец
DB::commit();

(Exeption еще можно поймать, что делать с Fatal Error и что происходит после такого с БД?)
2) Если где-то в процессе снова будет вызван DB::beginTransaction() - DB::commit()...
DB::beginTransaction();
// начало великолепного и полезного кода
//вызов восхитительной ф-ции, внутри которой тоже вызывается DB::beginTransaction(), 
//а потом DB::commit()
func(...);
//конец
DB::commit();

2.1) Какое поведение при повторном вызове DB::beginTransaction()?
2.2) Если DB::beginTransaction() ничего не меняет, что случится при вызове DB::commit()? Вся транзакция пох... закончится, не дождавшись DB::commit(), который как ожидает неосведомленный автор действительно завершит транзакцию?

3) (похож на 1) Если DB::commit(); вообще никто вызывать и не собирался?

P.S. (На упреждение) Документацию Laravel по транзакциям смотрел. Нашёл там только как нужно использовать и ни словом про возникшие вопросы.
Про (вот такой) рекомендуемый способ использовать транзакции я знаю:
DB::beginTransaction();

try {
    DB::insert(...);
    //.....

    DB::commit();
    // all good
} catch (\Exception $e) {
    DB::rollback();
    // something went wrong
}

Интересует именно как они работают когда все пошло не "по плану" и какие последствия можно получить.
  • Вопрос задан
  • 185 просмотров
Пригласить эксперта
Ответы на вопрос 3
@galaxy
Не скажу за Laravel (не пользуюсь), но скорее всего эти функции вызывают соответствующие команды БД (BEGIN/START TRANSACTION/COMMIT etc.). Поведение будет, вообще говоря, зависеть от БД.
Например, если код не дойдет до DB::commit();.

Транзакция откатится (если вы, конечно, не поймаете исключение, или, например, в том же соединении с БД не начнете новую транзакцию с успешным commit)

Если где-то в процессе снова будет вызван DB::beginTransaction() - DB::commit()...

Тут зависит от БД. Mysql, например, при повторном BEGIN закоммит текущую транзакцию и начнет новую. Postgres выдаст предупреждение и не изменит состояние транзакции.

Если DB::commit(); вообще никто вызывать и не собирался?

Транзакция откатится при закрытии соединения с БД.

Еще раз - выше написано про поведение БД, Laravel может иметь свои особенности.
Ответ написан
BojackHorseman
@BojackHorseman Куратор тега MySQL
...в творческом отпуске...
в общем случае любая транзакция будет откачена, если не получен явный коммит.
существуют исключения.
autocommit раз. операции, которые всегда коммитят транзакцию - два.
курить ман вашей субд.
в случае вложенных транзакций все работает с точностью до последнего разветвления, кроме операций, которые сразу коммитят всю иерархию транзакций.
Ответ написан
Alex_Wells
@Alex_Wells
PHP/TS/Kotlin developer
Не используйте ручное управление уровнем транзакции. Исключение - специфичные ситуации, где и так будет понятно, что оно нужно.

Отвечая на вопрос, DB::transaction(callable) откатит транзакцию при exception'е, остальное (ручное) управление - ничего автоматически не делает, за исключением хендлинга нескольких специфичных ерроров, которые сбрасывают уровень транзакции сами.

В общем в ручное управление лучше не лезть, ведь про*батся ОЧЕНЬ легко, дебажить - сложно, а лара не все просчитывает.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы