Skip to content

Instantly share code, notes, and snippets.

@sarjarapu
Created May 28, 2018 21:02
Show Gist options
  • Save sarjarapu/a8142a1e2bd84eeadf363ad945c79b29 to your computer and use it in GitHub Desktop.
Save sarjarapu/a8142a1e2bd84eeadf363ad945c79b29 to your computer and use it in GitHub Desktop.
MongoDB commands illustrating multiple transactions with write conflicts are aborted
// v4.0.0-rc0/bin/mongo --port 38000
// ****************************************************
// On a sample person collection with two documents _id 1, 2
// Update a document, _id 1, in session1 scope
// Delete a document, _id 2, in session1 scope
// Delete a document, _id 2, in session2 scope
// Understand how the find operation on these scopes change
// ****************************************************
// drop and recreate person collection with 2 documents _id 1, 2
use test;
db.person.drop();
db.person.insert({"_id": 1, "fname": "fname-1", "lname": "lname-1"});
db.person.insert({"_id": 2, "fname": "fname-2", "lname": "lname-2"});
// create session1 and a collection object using session1 and start a transaction on it
var session1 = db.getMongo().startSession();
var session1PersonColl = session1.getDatabase('test').getCollection('person');
session1.startTransaction({readConcern: {level: 'snapshot'}, writeConcern: {w: 'majority'}});
// create session2 and a collection object using session2 and start a transaction on it
var session2 = db.getMongo().startSession();
var session2PersonColl = session2.getDatabase('test').getCollection('person');
session2.startTransaction({readConcern: {level: 'snapshot'}, writeConcern: {w: 'majority'}});
// The find operations on all collections inside/outside transactions show same data
db.person.find()
session1PersonColl.find()
session2PersonColl.find()
// { "_id" : 1, "fname" : "fname-1", "lname" : "lname-1" }
// { "_id" : 2, "fname" : "fname-2", "lname" : "lname-2" }
// update a document _id 1, inside a transaction/session1
session1PersonColl.updateOne({"_id": 1}, {"$set": {"fname": "fname-1U", "lname": "lname-1U"}} );
// { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
// delete a document _id 2, inside a transaction/session1
session1PersonColl.deleteOne({"_id": 2});
// { "acknowledged" : true, "deletedCount" : 1 }
// The find operation on session1 shows modified _id 1 and no _id 2
session1PersonColl.find()
// { "_id" : 1, "fname" : "fname-1U", "lname" : "lname-1U" }
// The find operation on session2 shows unmodified _id 1 and _id 2
session2PersonColl.find()
// { "_id" : 1, "fname" : "fname-1", "lname" : "lname-1" }
// { "_id" : 2, "fname" : "fname-2", "lname" : "lname-2" }
// The delete _id 2 operation inside transaction/session2 would result
// in WriteConflict and session2 transaction being aborted
session2PersonColl.deleteOne({"_id": 2});
// 2018-05-28T08:59:04.545-0500 E QUERY [js] WriteCommandError: WriteConflict :
// WriteCommandError({
// "errorLabels" : [
// "TransientTransactionError"
// ],
// "operationTime" : Timestamp(1527515941, 1),
// "ok" : 0,
// "errmsg" : "WriteConflict",
// "code" : 112,
// "codeName" : "WriteConflict",
// "$clusterTime" : {
// "clusterTime" : Timestamp(1527515941, 1),
// "signature" : {
// "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
// "keyId" : NumberLong(0)
// }
// }
// })
// WriteCommandError@src/mongo/shell/bulk_api.js:420:48
// Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1
// Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21
// DBCollection.prototype.deleteOne@src/mongo/shell/crud_api.js:363:17
// @(shell):1:1
// The find operation on collection shows unmodified _id 1 and no _id 2
db.person.find()
// { "_id" : 1, "fname" : "fname-1", "lname" : "lname-1" }
// { "_id" : 2, "fname" : "fname-2", "lname" : "lname-2" }
// The find operation on session1's collection shows modified _id 1 and no _id 2
session1PersonColl.find()
// { "_id" : 1, "fname" : "fname-1U", "lname" : "lname-1U" }
// abort and end the session1 and session2
session1.abortTransaction()
session1.endSession()
session2.abortTransaction()
session2.endSession()
// The find operation on the collection now shows committed changes
db.person.find()
// { "_id" : 1, "fname" : "fname-1", "lname" : "lname-1" }
// { "_id" : 2, "fname" : "fname-2", "lname" : "lname-2" }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment