diff options
author | Nathan Louie <nathan.louie@10gen.com> | 2018-07-03 15:20:23 -0400 |
---|---|---|
committer | Nathan Louie <nathan.louie@10gen.com> | 2018-07-06 11:27:55 -0400 |
commit | 6d9ce16649c73ed1f5d45ed6ca88f61010b73ca9 (patch) | |
tree | bf5c0e0e0ffb4d89e45c0d0b1ed178757e421d2c | |
parent | 9a68eb0cc65a93233b4ff5746330f9eb77de9b90 (diff) | |
download | mongo-6d9ce16649c73ed1f5d45ed6ca88f61010b73ca9.tar.gz |
SERVER-35293 Add counts of active and inactive transactions to serverStatus
-rw-r--r-- | jstests/noPassthrough/server_transaction_metrics.js | 101 | ||||
-rw-r--r-- | src/mongo/db/server_transactions_metrics.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/transactions_stats.idl | 6 |
3 files changed, 103 insertions, 6 deletions
diff --git a/jstests/noPassthrough/server_transaction_metrics.js b/jstests/noPassthrough/server_transaction_metrics.js index d1b7727efaa..31dbcaf9091 100644 --- a/jstests/noPassthrough/server_transaction_metrics.js +++ b/jstests/noPassthrough/server_transaction_metrics.js @@ -8,6 +8,13 @@ assert(serverStatusResponse.hasOwnProperty("transactions"), "Expected the serverStatus response to have a 'transactions' field\n" + serverStatusResponse); + assert(serverStatusResponse.transactions.hasOwnProperty("currentActive"), + "The 'transactions' field in serverStatus did not have the 'currentActive' field\n" + + serverStatusResponse.transactions); + assert( + serverStatusResponse.transactions.hasOwnProperty("currentInactive"), + "The 'transactions' field in serverStatus did not have the 'currentInactive' field\n" + + serverStatusResponse.transactions); assert(serverStatusResponse.transactions.hasOwnProperty("currentOpen"), "The 'transactions' field in serverStatus did not have the 'currentOpen' field\n" + serverStatusResponse.transactions); @@ -41,6 +48,7 @@ const dbName = "test"; const collName = "server_transactions_metrics"; const testDB = primary.getDB(dbName); + const adminDB = rst.getPrimary().getDB('admin'); testDB.runCommand({drop: collName, writeConcern: {w: "majority"}}); assert.commandWorked(testDB.runCommand({create: collName, writeConcern: {w: "majority"}})); @@ -62,8 +70,13 @@ assert.commandWorked(sessionColl.insert({_id: "insert-1"})); let newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); verifyServerStatusFields(newStatus); - // Test that the open transaction counter is incremented while inside the transaction. + // Verify that the open transaction counter is incremented while inside the transaction. verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1); + // Verify that when not running an operation, the transaction is inactive. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 0); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 1); // Compare server status after the transaction commit with the server status before. session.commitTransaction(); @@ -72,8 +85,13 @@ verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalStarted", 1); verifyServerStatusChange( initialStatus.transactions, newStatus.transactions, "totalCommitted", 1); - // Test that current open counter is decremented on commit. + // Verify that current open counter is decremented on commit. verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0); + // Verify that both active and inactive are 0 on commit. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 0); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 0); // This transaction will abort. jsTest.log("Start a transaction and then abort it."); @@ -83,8 +101,13 @@ assert.commandWorked(sessionColl.insert({_id: "insert-2"})); newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); verifyServerStatusFields(newStatus); - // Test that the open transaction counter is incremented while inside the transaction. + // Verify that the open transaction counter is incremented while inside the transaction. verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1); + // Verify that when not running an operation, the transaction is inactive. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 0); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 1); // Compare server status after the transaction abort with the server status before. session.abortTransaction(); @@ -94,8 +117,13 @@ verifyServerStatusChange( initialStatus.transactions, newStatus.transactions, "totalCommitted", 1); verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalAborted", 1); - // Test that current open counter is decremented on abort. + // Verify that current open counter is decremented on abort. verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0); + // Verify that both active and inactive are 0 on abort. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 0); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 0); // This transaction will abort due to a duplicate key insert. jsTest.log("Start a transaction that will abort on a duplicated key error."); @@ -106,8 +134,13 @@ assert.commandWorked(sessionColl.insert({_id: "insert-3"})); newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); verifyServerStatusFields(newStatus); - // Test that the open transaction counter is incremented while inside the transaction. + // Verify that the open transaction counter is incremented while inside the transaction. verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1); + // Verify that when not running an operation, the transaction is inactive. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 0); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 1); // Compare server status after the transaction abort with the server status before. // The duplicated insert will fail, causing the transaction to abort. @@ -121,8 +154,64 @@ verifyServerStatusChange( initialStatus.transactions, newStatus.transactions, "totalCommitted", 1); verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "totalAborted", 2); - // Test that current open counter is decremented on abort caused by an error. + // Verify that current open counter is decremented on abort caused by an error. verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0); + // Verify that both active and inactive are 0 on abort. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 0); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 0); + + // Hang the transaction on a failpoint in the middle of an operation to check active and + // inactive counters while operation is running inside a transaction. + jsTest.log( + "Start a transaction that will hang in the middle of an operation due to a fail point."); + assert.commandWorked(testDB.adminCommand( + {configureFailPoint: 'setInterruptOnlyPlansCheckForInterruptHang', mode: 'alwaysOn'})); + assert.commandWorked( + testDB.adminCommand({setParameter: 1, internalQueryExecYieldIterations: 1})); + + const transactionFn = function() { + const collName = 'server_transactions_metrics'; + const session = db.getMongo().startSession({causalConsistency: false}); + const sessionDb = session.getDatabase('test'); + const sessionColl = sessionDb[collName]; + + session.startTransaction({readConcern: {level: 'snapshot'}}); + assert.commandWorked(sessionColl.update({}, {"update-1": 2})); + session.commitTransaction(); + }; + const transactionProcess = startParallelShell(transactionFn, primary.port); + + // Keep running currentOp() until we see the transaction subdocument. + assert.soon(function() { + const transactionFilter = + {active: true, 'lsid': {$exists: true}, 'transaction.parameters.txnNumber': {$eq: 0}}; + return 1 === adminDB.aggregate([{$currentOp: {}}, {$match: transactionFilter}]).itcount(); + }); + newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); + verifyServerStatusFields(newStatus); + // Verify that the open transaction counter is incremented while inside the transaction. + verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 1); + // Verify that the metrics show that the transaction is active while inside the operation. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 1); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 0); + + // Now the transaction can proceed. + assert.commandWorked(testDB.adminCommand( + {configureFailPoint: 'setInterruptOnlyPlansCheckForInterruptHang', mode: 'off'})); + transactionProcess(); + newStatus = assert.commandWorked(testDB.adminCommand({serverStatus: 1})); + verifyServerStatusFields(newStatus); + // Verify that current open counter is decremented on commit. + verifyServerStatusChange(initialStatus.transactions, newStatus.transactions, "currentOpen", 0); + // Verify that both active and inactive are 0 after the transaction finishes. + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentActive", 0); + verifyServerStatusChange( + initialStatus.transactions, newStatus.transactions, "currentInactive", 0); // End the session and stop the replica set. session.endSession(); diff --git a/src/mongo/db/server_transactions_metrics.cpp b/src/mongo/db/server_transactions_metrics.cpp index 6907d94c206..b573996b50b 100644 --- a/src/mongo/db/server_transactions_metrics.cpp +++ b/src/mongo/db/server_transactions_metrics.cpp @@ -112,6 +112,8 @@ void ServerTransactionsMetrics::incrementTotalCommitted() { } void ServerTransactionsMetrics::updateStats(TransactionsStats* stats) { + stats->setCurrentActive(_currentActive.load()); + stats->setCurrentInactive(_currentInactive.load()); stats->setCurrentOpen(_currentOpen.load()); stats->setTotalAborted(_totalAborted.load()); stats->setTotalCommitted(_totalCommitted.load()); diff --git a/src/mongo/db/transactions_stats.idl b/src/mongo/db/transactions_stats.idl index 616e165cd9f..f6f6504d1f0 100644 --- a/src/mongo/db/transactions_stats.idl +++ b/src/mongo/db/transactions_stats.idl @@ -39,6 +39,12 @@ structs: transactionsCollectionWriteCount: type: long default: 0 + currentActive: + type: long + default: 0 + currentInactive: + type: long + default: 0 currentOpen: type: long default: 0 |