@@ -9,71 +9,150 @@ Transactions
9
9
:values: tutorial
10
10
11
11
.. meta::
12
- :keywords: php framework, odm, code example
12
+ :keywords: php framework, odm, rollback, commit, callback, code example, acid, atomic, consistent, isolated, durable
13
13
14
- MongoDB transactions require the following software and topology:
14
+ .. contents:: On this page
15
+ :local:
16
+ :backlinks: none
17
+ :depth: 2
18
+ :class: singlecol
19
+
20
+ Overview
21
+ --------
22
+
23
+ In this guide, you can learn how to perform a **transaction** in MongoDB by
24
+ using the {+odm-long+}. Transactions let you run a sequence of write operations
25
+ that update the data only after the transaction is committed.
26
+
27
+ If the transaction fails, the PHP library that manages MongoDB operations
28
+ for {+odm-short+} ensures that MongoDB discards all the changes made within
29
+ the transaction before they become visible. This property of transactions
30
+ that ensures that all changes within a transaction are either applied or
31
+ discarded is called **atomicity**.
32
+
33
+ MongoDB performs write operations on single documents atomically. If you
34
+ need atomicity in write operations on multiple documents or data consistency
35
+ across multiple documents for your operations, run them in a multi-document
36
+ transaction.
37
+
38
+ Multi-document transactions are **ACID compliant** because MongoDB
39
+ guarantees that the data in your transaction operations remains consistent,
40
+ even if the driver encounters unexpected errors.
41
+
42
+ Learn how to perform transactions in the following sections of this guide:
43
+
44
+ - :ref:`laravel-transaction-requirements`
45
+ - :ref:`laravel-transaction-callback`
46
+ - :ref:`laravel-transaction-commit`
47
+ - :ref:`laravel-transaction-rollback`
48
+
49
+ .. tip::
50
+
51
+ To learn more about transactions in MongoDB, see :manual:`Transactions </core/transactions/>`
52
+ in the {+server-docs-name+}.
53
+
54
+ .. _laravel-transaction-requirements:
55
+
56
+ Requirements and Limitations
57
+ ----------------------------
58
+
59
+ To perform transactions in MongoDB, you must use the following MongoDB
60
+ version and topology:
15
61
16
62
- MongoDB version 4.0 or later
17
63
- A replica set deployment or sharded cluster
18
64
19
- You can find more information :manual:`in the MongoDB docs </core/transactions/>`
65
+ MongoDB server and {+odm-short+} have the following limitations:
20
66
21
- .. code-block:: php
67
+ - In MongoDB versions 4.2 and earlier, write operations performed within a
68
+ transaction must be on existing collections. In MongoDB versions 4.4 and
69
+ later, the server automatically creates collections as necessary when
70
+ you perform write operations in a transaction. To learn more about this
71
+ limitation, see :manual:`Create Collections and Indexes in a Transaction </core/transactions/#create-collections-and-indexes-in-a-transaction>`
72
+ in the {+server-docs-name+}.
73
+ - MongoDB does not support nested transactions. If you attempt to start a
74
+ transaction within another one, the extension raises a ``RuntimeException``.
75
+ To learn more about this limitation, see :manual:`Transactions and Sessions </core/transactions/#transactions-and-sessions>`
76
+ in the {+server-docs-name+}.
77
+ - The {+odm-long+} does not support the database testing traits
78
+ ``Illuminate\Foundation\Testing\DatabaseTransactions`` and ``Illuminate\Foundation\Testing\RefreshDatabase``.
79
+ As a workaround, you can create migrations with the ``Illuminate\Foundation\Testing\DatabaseMigrations``
80
+ trait to reset the database after each test.
22
81
23
- DB::transaction(function () {
24
- User::create(['name' => 'john', 'age' => 19, 'title' => 'admin', 'email' => '
[email protected] ']);
25
- DB::collection('users')->where('name', 'john')->update(['age' => 20]);
26
- DB::collection('users')->where('name', 'john')->delete();
27
- });
82
+ .. _laravel-transaction-callback:
28
83
29
- .. code-block:: php
84
+ Run a Transaction in a Callback
85
+ -------------------------------
86
+
87
+ This section shows how you can run a transaction in a callback.
30
88
31
- // begin a transaction
32
- DB::beginTransaction();
33
- User::create(['name' => 'john', 'age' => 19, 'title' => 'admin', 'email' => '
[email protected] ']);
34
- DB::collection('users')->where('name', 'john')->update(['age' => 20]);
35
- DB::collection('users')->where('name', 'john')->delete();
89
+ When using this method of running a transaction, all the code in the
90
+ callback method runs as a single transaction.
36
91
37
- // commit changes
38
- DB::commit();
92
+ In the following example, the transaction consists of write operations that
93
+ transfer the funds from a bank account, represented by the ``Account`` model,
94
+ to another account:
39
95
40
- To abort a transaction, call the ``rollBack`` method at any point during the transaction:
96
+ .. literalinclude:: /includes/fundamentals/transactions/TransactionsTest.php
97
+ :language: php
98
+ :dedent:
99
+ :start-after: begin transaction callback
100
+ :end-before: end transaction callback
101
+
102
+ 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:
41
103
42
104
.. code-block:: php
105
+ :emphasize-lines: 4
43
106
44
- DB::beginTransaction();
45
- User::create(['name' => 'john', 'age' => 19, 'title' => 'admin', 'email' => '
[email protected] ']);
107
+ DB::transaction(function() {
108
+ // transaction code
109
+ },
110
+ retries: 5,
111
+ );
46
112
47
- // Abort the transaction, discarding any data created as part of it
48
- DB::rollBack();
113
+ .. _laravel-transaction-commit:
49
114
115
+ Begin and Commit a Transaction
116
+ ------------------------------
50
117
51
- .. note::
118
+ This section shows how to start and commit a transaction.
52
119
53
- Transactions in MongoDB cannot be nested. DB::beginTransaction() function
54
- will start new transactions in a new created or existing session and will
55
- raise the RuntimeException when transactions already exist. See more in
56
- MongoDB official docs :manual:`Transactions and Sessions </core/transactions/#transactions-and-sessions>` .
120
+ To use this method of starting and committing a transaction, call the
121
+ ``DB::beginTransaction()`` method to start the transaction. Then, call the
122
+ ``DB::commit()`` method to end the transaction, which applies all the updates
123
+ performed within the transaction .
57
124
58
- .. code-block:: php
125
+ In the following example, the balance from the first account is moved to the
126
+ second account, after which the first account is deleted:
59
127
60
- DB::beginTransaction();
61
- User::create(['name' => 'john', 'age' => 20, 'title' => 'admin']);
128
+ .. literalinclude:: /includes/fundamentals/transactions/TransactionsTest.php
129
+ :language: php
130
+ :dedent:
131
+ :emphasize-lines: 1,9
132
+ :start-after: begin commit transaction
133
+ :end-before: end commit transaction
62
134
63
- // This call to start a nested transaction will raise a RuntimeException
64
- DB::beginTransaction();
65
- DB::collection('users')->where('name', 'john')->update(['age' => 20]);
66
- DB::commit();
67
- DB::rollBack();
135
+ .. _laravel-transaction-rollback:
68
136
69
- Database Testing
70
- ----------------
137
+ Roll Back a Transaction
138
+ -----------------------
71
139
72
- For testing, the traits ``Illuminate\Foundation\Testing\DatabaseTransactions``
73
- and ``Illuminate\Foundation\Testing\RefreshDatabase`` are not yet supported.
74
- Instead, create migrations and use the ``DatabaseMigrations`` trait to reset
75
- the database after each test:
140
+ This section shows how to roll back a transaction. A rollback reverts all the
141
+ write operations performed within that transaction. This means that the
142
+ data is reverted to its state before the transaction.
76
143
77
- .. code-block:: php
144
+ To perform the rollback, call the ``DB::rollback()`` function anytime before
145
+ the transaction is committed.
146
+
147
+ In the following example, the transaction consists of write operations that
148
+ transfer funds from one account, represented by the ``Account`` model, to
149
+ multiple other accounts. If the sender account has insufficient funds, the
150
+ transaction is rolled back, and none of the models are updated:
151
+
152
+ .. literalinclude:: /includes/fundamentals/transactions/TransactionsTest.php
153
+ :language: php
154
+ :dedent:
155
+ :emphasize-lines: 1,18,20
156
+ :start-after: begin rollback transaction
157
+ :end-before: end rollback transaction
78
158
79
- use Illuminate\Foundation\Testing\DatabaseMigrations;
0 commit comments