Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Події
Інше
Про нас
Senior Database

Чому транзакція не рятує від листа, який уже пішов?

Транзакція відкочує записи в базу - і більше нічого. Усе, що встигло вийти за її межі, лишається зробленим.

П'ять місць, де це видно:

1. Побічні ефекти не відкочуються. Лист, відправлений усередині транзакції, піде навіть після rollback - база відкотиться, а користувач уже отримав «Замовлення оформлено».

2. Завдання стартує раніше за commit. Воркер може взяти завдання до завершення транзакції й не знайти запису. Лікується afterCommit() на завданні або ShouldDispatchAfterCommit на події:

ProcessOrder::dispatch($order)->afterCommit();

3. Вкладені транзакції - не транзакції. Друга DB::transaction() усередині першої не створює окрему: використовуються savepoint-и, і зовнішній rollback скасує все одно все.

4. DDL не відкочується в MySQL. Schema::create() усередині транзакції робить неявний commit - міграції на MySQL атомарними не бувають, на відміну від PostgreSQL.

5. Довга транзакція тримає блокування. Звернення до зовнішнього API всередині транзакції означає, що рядки заблоковані на весь час мережевого очікування.

Практичне правило: усередині транзакції - лише запити до бази. Листи, черги, HTTP - після неї, за фактом успіху.

Докладніше в документації: База даних: транзакції

2

Схожі питання