diff options
author | Louis Williams <louis.williams@mongodb.com> | 2019-04-12 11:39:39 -0400 |
---|---|---|
committer | Louis Williams <louis.williams@mongodb.com> | 2019-04-12 11:39:39 -0400 |
commit | ee9c8b7d7382cb7f91b72c2e680f18016754ee35 (patch) | |
tree | 5481fcb8a9a6514a63cba6b699287b5aef2e61a3 /jstests | |
parent | c6560dd65c6a2eac9f83045e6197d7dbce512c6e (diff) | |
download | mongo-ee9c8b7d7382cb7f91b72c2e680f18016754ee35.tar.gz |
SERVER-40105 Improve diagnostic information in currentOp for writeConflicts and prepareConflicts
Diffstat (limited to 'jstests')
-rw-r--r-- | jstests/core/txns/currentop_blocked_operations.js | 83 | ||||
-rw-r--r-- | jstests/core/txns/write_conflicts_with_non_txns.js | 3 |
2 files changed, 85 insertions, 1 deletions
diff --git a/jstests/core/txns/currentop_blocked_operations.js b/jstests/core/txns/currentop_blocked_operations.js new file mode 100644 index 00000000000..8e51334bdff --- /dev/null +++ b/jstests/core/txns/currentop_blocked_operations.js @@ -0,0 +1,83 @@ +/** + * Tests that currentOp reports debug information for operations that are blocked on transactions. + * + * @tags: [uses_transactions, uses_prepare_transaction] + */ +(function() { + "use strict"; + load("jstests/core/txns/libs/prepare_helpers.js"); + + const dbName = "test"; + const collName = "currentop_blocked_operations"; + const testDB = db.getSiblingDB(dbName); + const testColl = testDB.getCollection(collName); + + testColl.drop({writeConcern: {w: "majority"}}); + assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}})); + + const session = db.getMongo().startSession(); + const sessionDB = session.getDatabase(dbName); + const sessionColl = sessionDB.getCollection(collName); + + // Returns when the operation matching the 'matchExpr' is blocked, as evaluated by the + // 'isBlockedFunc'. + let waitForBlockedOp = function(matchExpr, isBlockedFunc) { + assert.soon(function() { + let cursor = + db.getSiblingDB("admin").aggregate([{$currentOp: {}}, {$match: matchExpr}]); + if (cursor.hasNext()) { + let op = cursor.next(); + printjson(op); + return isBlockedFunc(op); + } + return false; + }); + }; + + // This transaction will block conflicting non-transactional operations. + session.startTransaction(); + assert.commandWorked(sessionColl.insert({_id: 2222})); + + // This insert operation will encounter a WriteConflictException due to the unique key + // violation. It will block in an infinite write conflict loop until the transaction completes. + TestData.dbName = dbName; + TestData.collName = collName; + let awaitInsert = startParallelShell(function() { + let coll = db.getSiblingDB(TestData.dbName).getCollection(TestData.collName); + assert.commandWorked(coll.insert({_id: 2222, x: 0})); + }); + + // Wait for the counter to reach a high enough number to confirm the operation is retrying + // constantly. + waitForBlockedOp({"command.insert": collName}, function(op) { + return op.writeConflicts > 20; + }); + + assert.commandWorked(session.abortTransaction_forTesting()); + awaitInsert(); + assert.eq(1, testColl.find({_id: 2222, x: 0}).itcount()); + + // This prepared transaction will block conflicting non-transactional operations. + session.startTransaction(); + assert.commandWorked(sessionColl.update({_id: 2222}, {$set: {x: 1}})); + PrepareHelpers.prepareTransaction(session); + + // This update operation will encounter a prepare conflict due to the prepared transaction's + // modification to the same document. It will block without retrying until the prepared + // transaction completes. + TestData.dbName = dbName; + TestData.collName = collName; + let awaitUpdate = startParallelShell(function() { + let coll = db.getSiblingDB(TestData.dbName).getCollection(TestData.collName); + assert.commandWorked(coll.update({_id: 2222}, {$set: {x: 999}})); + }); + + // Expect at least one prepare conflict. + waitForBlockedOp({ns: testColl.getFullName(), op: "update"}, function(op) { + return op.prepareReadConflicts > 0; + }); + + assert.commandWorked(session.abortTransaction_forTesting()); + awaitUpdate(); + assert.eq(1, testColl.find({_id: 2222, x: 999}).itcount()); +})(); diff --git a/jstests/core/txns/write_conflicts_with_non_txns.js b/jstests/core/txns/write_conflicts_with_non_txns.js index 5d7c1cdd589..c198c85084c 100644 --- a/jstests/core/txns/write_conflicts_with_non_txns.js +++ b/jstests/core/txns/write_conflicts_with_non_txns.js @@ -52,7 +52,8 @@ // Returns true if a single document insert has started running on the server. function writeStarted() { return testDB.currentOp().inprog.some(op => { - return op.active && (op.ns === testColl.getFullName()) && (op.op === "insert"); + return op.active && (op.ns === testColl.getFullName()) && (op.op === "insert") && + (op.writeConflicts > 0); }); } |