Transactions and locks
DB::transaction
The transaction method runs a closure inside one database transaction. If the closure finishes, Laravel commits everything, and if it throws, every change rolls back together.
use Illuminate\Support\Facades\DB; DB::transaction(function () use ($order) { $order->update(["status" => "paid"]); });
Manual control
Long or branching flows may need explicit control instead of a closure. Begin the transaction by hand, commit on success, and roll back inside the catch block on any failure.
use Illuminate\Support\Facades\DB; try { DB::beginTransaction(); DB::commit(); } catch (Throwable $e) { DB::rollBack(); }
Lock rows
Two requests can read the same balance before either writes, which loses one update. The lockForUpdate method locks the selected rows until the transaction ends, forcing the second reader to wait.
use Illuminate\Support\Facades\DB; $user = DB::table("users") ->where("id", 1) ->lockForUpdate() ->first();
Retry note
Locked rows can deadlock when two transactions wait on each other, so the database kills one of them. Pass an attempt count as the second argument and Laravel retries the closure that many times.
use Illuminate\Support\Facades\DB; DB::transaction(function () use ($order) { $order->update(["status" => "paid"]); }, 3);
Next: Deployment
Article author: Arthur Isaev