Skip to content

Commit fc0555b

Browse files
committed
SERVER-38015 Test many concurrent transactions
1 parent 702d0c3 commit fc0555b

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

jstests/core/txns/many_txns.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// SERVER-38015 Test having many interactive transactions to ensure we don't hold on to too
2+
// many resources (like "write tickets") and don't prevent other operations from succeeding.
3+
// @tags: [uses_transactions]
4+
(function() {
5+
"use strict";
6+
7+
const dbName = "test";
8+
const collName = "many_txns";
9+
const numTxns = 150;
10+
11+
const testDB = db.getSiblingDB(dbName);
12+
const coll = testDB[collName];
13+
14+
testDB.runCommand({drop: collName, writeConcern: {w: "majority"}});
15+
assert.commandWorked(
16+
testDB.runCommand({create: coll.getName(), writeConcern: {w: "majority"}}));
17+
18+
const sessionOptions = {causalConsistency: false};
19+
20+
const startTime = new Date();
21+
22+
// Non-transactional write to give something to find.
23+
const initialDoc = {_id: "pretransaction1", x: 0};
24+
assert.commandWorked(coll.insert(initialDoc, {writeConcern: {w: "majority"}}));
25+
26+
// Start many transactions, each inserting two documents.
27+
jsTest.log("Start " + numTxns + " transactions, each inserting two documents");
28+
var sessions = [];
29+
for (let txnNr = 0; txnNr < numTxns; ++txnNr) {
30+
const session = testDB.getMongo().startSession(sessionOptions);
31+
sessions[txnNr] = session;
32+
const sessionDb = session.getDatabase(dbName);
33+
const sessionColl = sessionDb[collName];
34+
let doc = seq => ({_id: "txn-" + txnNr + "-" + seq});
35+
36+
session.startTransaction();
37+
38+
let docs = sessionColl.find({}).toArray();
39+
assert.sameMembers(docs, [initialDoc]);
40+
41+
// Insert a doc within the transaction.
42+
assert.commandWorked(sessionColl.insert(doc(1)));
43+
44+
// Read in the same transaction returns the doc, but not from other txns.
45+
docs = sessionColl.find({_id: {$ne: initialDoc._id}}).toArray();
46+
assert.sameMembers(docs, [doc(1)]);
47+
48+
// Insert a doc within a transaction.
49+
assert.commandWorked(sessionColl.insert(doc(2)));
50+
}
51+
const secondDoc = {_id: "midtransactions", x: 1};
52+
assert.commandWorked(coll.insert(secondDoc, {writeConcern: {w: "majority"}}));
53+
54+
// Commit all sessions.
55+
jsTest.log("Commit all transactions.");
56+
let numAborted = 0;
57+
for (let txnNr = 0; txnNr < numTxns; ++txnNr) {
58+
// First check that a non-transactional operation conflicts and times out quickly.
59+
let doc = seq => ({_id: "txn-" + txnNr + "-" + seq});
60+
let insertCmd = {insert: collName, documents: [doc(1)], maxTimeMS: 10};
61+
let insertRes = testDB.runCommand(insertCmd);
62+
63+
const session = sessions[txnNr];
64+
let commitRes = session.commitTransaction_forTesting();
65+
if (commitRes.code === ErrorCodes.NoSuchTransaction) {
66+
++numAborted;
67+
continue;
68+
}
69+
assert.commandWorked(commitRes, "couldn't commit transaction " + txnNr);
70+
assert.commandFailedWithCode(insertRes, ErrorCodes.MaxTimeMSExpired, tojson({insertCmd}));
71+
72+
// Read with default read concern sees the committed transaction.
73+
assert.eq(doc(1), coll.findOne(doc(1)));
74+
assert.eq(doc(2), coll.findOne(doc(2)));
75+
session.endSession();
76+
}
77+
78+
assert.eq(initialDoc, coll.findOne(initialDoc));
79+
assert.eq(secondDoc, coll.findOne(secondDoc));
80+
81+
const elapsedTime = new Date() - startTime;
82+
jsTest.log("Test completed with " + numAborted + " aborted transactions in " + elapsedTime +
83+
" ms");
84+
85+
// Check whether we should expect aborts. If the parameter doesn't exist (mongos) don't check.
86+
const getParamRes = db.adminCommand({getParameter: 1, transactionLifetimeLimitSeconds: 1});
87+
if (getParamRes.ok && elapsedTime < getParamRes.transactionLifetimeLimitSeconds)
88+
assert.eq(numAborted,
89+
0,
90+
"should not get aborts when transactionLifetimeLimitSeconds not exceeded");
91+
}());

0 commit comments

Comments
 (0)