diff options
author | A. Jesse Jiryu Davis <jesse@mongodb.com> | 2019-03-29 17:48:58 -0400 |
---|---|---|
committer | A. Jesse Jiryu Davis <jesse@mongodb.com> | 2019-04-08 11:44:59 -0400 |
commit | f8f872e029ba3b1f32d8499c912756d48dc1a03b (patch) | |
tree | 8e024a7746bfbf12f296b0bcb45ab73a17779922 /jstests/replsets/initial_sync_preserves_active_txns.js | |
parent | 612457dcfc3ba939dc8474f227f9166520a4a583 (diff) | |
download | mongo-f8f872e029ba3b1f32d8499c912756d48dc1a03b.tar.gz |
SERVER-36494 Test that active txn entries aren't truncated
Add tests for initial sync, recovery, and the inMemory storage engine.
Also, avoid taking a global X lock in replSetReconfig, we only need IX.
Diffstat (limited to 'jstests/replsets/initial_sync_preserves_active_txns.js')
-rw-r--r-- | jstests/replsets/initial_sync_preserves_active_txns.js | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/jstests/replsets/initial_sync_preserves_active_txns.js b/jstests/replsets/initial_sync_preserves_active_txns.js new file mode 100644 index 00000000000..4e9f1ad1dcb --- /dev/null +++ b/jstests/replsets/initial_sync_preserves_active_txns.js @@ -0,0 +1,76 @@ +/** + * When the oplog size grows during initial sync to exceed the configured maximum, the node must + * truncate the oplog only up to the oldest active transaction timestamp at the time of the last + * stable checkpoint. The first oplog entry that belongs to an active transaction is preserved, and + * all entries after it. + * + * This tests the oldestActiveTransactionTimestamp, which is calculated from the "startOpTime" + * field of documents in the config.transactions collection. + * + * @tags: [uses_transactions, uses_prepare_transaction] + */ + +(function() { + "use strict"; + load("jstests/core/txns/libs/prepare_helpers.js"); + + const replSet = new ReplSetTest({ + // Oplog can be truncated each "sync" cycle. Increase its frequency to once per second. + nodeOptions: {syncdelay: 1, setParameter: {logComponentVerbosity: tojson({storage: 1})}}, + nodes: 1 + }); + + replSet.startSet(PrepareHelpers.replSetStartSetOptions); + replSet.initiate(); + const primary = replSet.getPrimary(); + const primaryOplog = primary.getDB("local").oplog.rs; + assert.lte(primaryOplog.dataSize(), PrepareHelpers.oplogSizeBytes); + + const coll = primary.getDB("test").test; + assert.commandWorked(coll.insert({}, {writeConcern: {w: "majority"}})); + + jsTestLog("Prepare a transaction"); + + const session = primary.startSession(); + session.startTransaction(); + assert.commandWorked(session.getDatabase("test").test.insert({myTransaction: 1})); + const prepareTimestamp = PrepareHelpers.prepareTransaction(session); + const txnEntry = primary.getDB("config").transactions.findOne(); + assert.eq(txnEntry.startOpTime.ts, prepareTimestamp, tojson(txnEntry)); + + jsTestLog("Insert documents until oplog exceeds oplogSize"); + + // Oplog with prepared txn grows indefinitely - let it reach twice its supposed max size. + PrepareHelpers.growOplogPastMaxSize(replSet); + + jsTestLog("Find prepare oplog entry"); + + const oplogEntry = primaryOplog.findOne({prepare: true}); + assert.eq(oplogEntry.ts, prepareTimestamp, tojson(oplogEntry)); + + jsTestLog("Add a secondary node"); + + const secondary = replSet.add({rsConfig: {votes: 0, priority: 0}}); + replSet.reInitiate(); + + jsTestLog("Reinitiated, awaiting secondary node"); + + replSet.awaitSecondaryNodes(); + + jsTestLog("Checking secondary oplog and config.transactions"); + + // Oplog grew past maxSize, and it includes the oldest active transaction's entry. + const secondaryOplog = secondary.getDB("local").oplog.rs; + assert.gt(secondaryOplog.dataSize(), PrepareHelpers.oplogSizeBytes); + const secondaryOplogEntry = secondaryOplog.findOne({prepare: true}); + assert.eq(secondaryOplogEntry.ts, prepareTimestamp, tojson(secondaryOplogEntry)); + + const secondaryTxnEntry = secondary.getDB("config").transactions.findOne(); + assert.eq(secondaryTxnEntry, txnEntry, tojson(secondaryTxnEntry)); + + // TODO(SERVER-36492): commit or abort, await oplog truncation + // See recovery_preserves_active_txns.js for example. + // Until then, skip validation, the stashed transaction's lock prevents validation. + TestData.skipCheckDBHashes = true; + replSet.stopSet(undefined, undefined, {skipValidation: true}); +})(); |