Docs Menu

Docs HomeDevelop ApplicationsPHP DriverLaravel MongoDB

Transactions

On this page

  • Overview
  • Requirements and Limitations
  • Run a Transaction in a Callback
  • Begin and Commit a Transaction
  • Roll Back a Transaction

In this guide, you can learn how to perform a transaction in MongoDB by using the Laravel MongoDB package. Transactions let you run a sequence of write operations that update the data only after the transaction is committed.

If the transaction fails, the MongoDB PHP Library that manages MongoDB operations for Laravel MongoDB ensures that MongoDB discards all the changes made within the transaction before they become visible. This property of transactions that ensures that all changes within a transaction are either applied or discarded is called atomicity.

MongoDB performs write operations on single documents atomically. If you need atomicity in write operations on multiple documents or data consistency across multiple documents for your operations, run them in a multi-document transaction.

Multi-document transactions are ACID compliant because MongoDB guarantees that the data in your transaction operations remains consistent, even if the driver encounters unexpected errors.

Learn how to perform transactions in the following sections of this guide:

  • Requirements and Limitations

  • Run a Transaction in a Callback

  • Begin and Commit a Transaction

  • Roll Back a Transaction

Tip

To learn more about transactions in MongoDB, see Transactions in the Server manual.

To perform transactions in MongoDB, you must use the following MongoDB version and topology:

  • MongoDB version 4.0 or later

  • A replica set deployment or sharded cluster

MongoDB server and Laravel MongoDB have the following limitations:

  • In MongoDB versions 4.2 and earlier, write operations performed within a transaction must be on existing collections. In MongoDB versions 4.4 and later, the server automatically creates collections as necessary when you perform write operations in a transaction. To learn more about this limitation, see Create Collections and Indexes in a Transaction in the Server manual.

  • MongoDB does not support nested transactions. If you attempt to start a transaction within another one, the extension raises a RuntimeException. To learn more about this limitation, see Transactions and Sessions in the Server manual.

  • The Laravel MongoDB package does not support the database testing traits Illuminate\Foundation\Testing\DatabaseTransactions and Illuminate\Foundation\Testing\RefreshDatabase. As a workaround, you can create migrations with the Illuminate\Foundation\Testing\DatabaseMigrations trait to reset the database after each test.

This section shows how you can run a transaction in a callback.

When using this method of running a transaction, all the code in the callback method runs as a single transaction.

In the following example, the transaction consists of write operations that transfer the funds from a bank account, represented by the Account model, to another account:

DB::transaction(function () {
$transferAmount = 200;
$sender = Account::where('number', 223344)->first();
$sender->balance -= $transferAmount;
$sender->save();
$receiver = Account::where('number', 776655)->first();
$receiver->balance += $transferAmount;
$receiver->save();
});

You can optionally pass the maximum number of times to retry a failed transaction as the second parameter as shown in the following code example:

DB::transaction(function() {
// transaction code
},
retries: 5,
);

This section shows how to start and commit a transaction.

To use this method of starting and committing a transaction, call the DB::beginTransaction() method to start the transaction. Then, call the DB::commit() method to end the transaction, which applies all the updates performed within the transaction.

In the following example, the balance from the first account is moved to the second account, after which the first account is deleted:

DB::beginTransaction();
$oldAccount = Account::where('number', 223344)->first();
$newAccount = Account::where('number', 776655)->first();
$newAccount->balance += $oldAccount->balance;
$newAccount->save();
$oldAccount->delete();
DB::commit();

This section shows how to roll back a transaction. A rollback reverts all the write operations performed within that transaction. This means that the data is reverted to its state before the transaction.

To perform the rollback, call the DB::rollback() function anytime before the transaction is committed.

In the following example, the transaction consists of write operations that transfer funds from one account, represented by the Account model, to multiple other accounts. If the sender account has insufficient funds, the transaction is rolled back, and none of the models are updated:

DB::beginTransaction();
$sender = Account::where('number', 223344)->first();
$receiverA = Account::where('number', 776655)->first();
$receiverB = Account::where('number', 990011)->first();
$amountA = 100;
$amountB = 200;
$sender->balance -= $amountA;
$receiverA->balance += $amountA;
$sender->balance -= $amountB;
$receiverB->balance += $amountB;
if ($sender->balance < 0) {
// insufficient balance, roll back the transaction
DB::rollback();
} else {
DB::commit();
}
← Queues