@@ -207,37 +207,87 @@ content: |
207
207
ref : transactions-stale-reads
208
208
content : |
209
209
210
- Read operations inside a transaction can return stale data. That is,
211
- read operations inside a transaction are not guaranteed to see
212
- writes performed by other committed transactions or
213
- non-transactional writes. For
214
- example, consider the following sequence: 1) a transaction is
215
- in-progress 2) a write outside the transaction deletes a document 3)
216
- a read operation inside the transaction is able to read the
217
- now-deleted document since the operation is using a snapshot from
218
- before the write.
210
+ Read operations inside a transaction can return old data, which is known as a
211
+ :term:`stale read`. Read operations inside a transaction are not guaranteed
212
+ to see writes performed by other committed transactions or
213
+ non-transactional writes. For example, consider the following sequence:
214
+
215
+ #. A transaction is in-progress.
216
+
217
+ #. A write outside the transaction deletes a document.
218
+
219
+ #. A read operation inside the transaction can read the now-deleted document
220
+ since the operation uses a snapshot from before the write operation.
219
221
220
222
To avoid stale reads inside transactions for a single document, you
221
- can use the :method:`db.collection.findOneAndUpdate()` method. For
222
- example:
223
-
224
- .. code-block:: javascript
225
-
226
- session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
227
-
228
- employeesCollection = session.getDatabase("hr").employees;
229
-
230
- employeeDoc = employeesCollection.findOneAndUpdate(
231
- { _id: 1, employee: 1, status: "Active" },
232
- { $set: { employee: 1 } },
233
- { returnNewDocument: true }
234
- );
235
-
236
- - If the employee document has changed outside the transaction, then
237
- the transaction aborts.
223
+ can use the :method:`db.collection.findOneAndUpdate()` method. The following
224
+ :binary:`~bin.mongosh` example demonstrates how you can use
225
+ ``db.collection.findOneAndUpdate()`` to take a :term:`write lock` and ensure
226
+ that your reads are up to date:
227
+
228
+ .. procedure::
229
+ :style: normal
230
+
231
+ .. step:: Insert a document into the ``employees`` collection
232
+
233
+ .. code-block:: javascript
234
+ :copyable: true
235
+
236
+ db.getSiblingDB("hr").employees.insertOne(
237
+ { _id: 1, status: "Active" }
238
+ )
239
+
240
+ .. step:: Start a session
241
+
242
+ .. code-block:: javascript
243
+ :copyable: true
244
+
245
+ session = db.getMongo().startSession( { readPreference: { mode: "primary" } } )
246
+
247
+ .. step:: Start a transaction
248
+
249
+ .. code-block:: javascript
250
+ :copyable: true
251
+
252
+ session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } )
253
+
254
+ employeesCollection = session.getDatabase("hr").employees
255
+
256
+ .. step:: Use ``db.collection.findOneAndUpdate()`` inside the transaction
257
+
258
+ .. code-block:: javascript
259
+ :copyable: true
260
+
261
+ employeeDoc = employeesCollection.findOneAndUpdate(
262
+ { _id: 1, status: "Active" },
263
+ { $set: { lockId: ObjectId() } },
264
+ { returnNewDocument: true }
265
+ )
266
+
267
+ Note that inside the transaction, the ``findOneAndUpdate`` operation
268
+ sets a new ``lockId`` field. You can set ``lockId`` field to any
269
+ value, as long as it modifies the document. By updating the
270
+ document, the transaction acquires a lock.
271
+
272
+ If an operation outside of the transaction attempts to modify the
273
+ document before you commit the transaction, MongoDB returns a write
274
+ conflict error to the external operation.
275
+
276
+ .. step:: Commit the transaction
277
+
278
+ .. code-block:: javascript
279
+ :copyable: true
280
+
281
+ session.commitTransaction()
282
+
283
+ After you commit the transaction, MongoDB releases the lock.
284
+
285
+ .. note::
286
+
287
+ If any operation in the transaction fails, the transaction
288
+ aborts and all data changes made in the transaction are discarded
289
+ without ever becoming visible in the collection.
238
290
239
- - If the employee document has not changed, the transaction returns
240
- the document and locks the document.
241
291
---
242
292
ref : transactions-read-concern-majority
243
293
content : |
0 commit comments