diff options
author | Pavi Vetriselvan <pvselvan@umich.edu> | 2019-04-01 13:42:11 -0400 |
---|---|---|
committer | Pavi Vetriselvan <pvselvan@umich.edu> | 2019-04-01 14:05:19 -0400 |
commit | e433a5aee915568cf73b05e89597903855ed1952 (patch) | |
tree | 6c05ba3dab362405e8d07cc5bf65ea86003ddbbf /jstests/replsets | |
parent | e96547906836a12d76b7a1591a0028b1fff8cb79 (diff) | |
download | mongo-e433a5aee915568cf73b05e89597903855ed1952.tar.gz |
Revert "SERVER-35811 disallow committing at the prepareTimestamp and pin stable TS before oldest uncommitted TS"
This reverts commit b58420e57a2149c350ebf82815fe708850402296 and 33ac1afd4079e04d12554f9b79d1ab07426caf59.
Diffstat (limited to 'jstests/replsets')
18 files changed, 91 insertions, 52 deletions
diff --git a/jstests/replsets/commit_prepared_transaction_before_stable_timestamp.js b/jstests/replsets/commit_prepared_transaction_before_stable_timestamp.js new file mode 100644 index 00000000000..71ca1189b45 --- /dev/null +++ b/jstests/replsets/commit_prepared_transaction_before_stable_timestamp.js @@ -0,0 +1,59 @@ +/** + * Test that we can successfully commit a prepared transaction before the stable timestamp. + * + * @tags: [uses_transactions, uses_prepare_transaction] + */ + +(function() { + "use strict"; + load("jstests/aggregation/extras/utils.js"); + load("jstests/core/txns/libs/prepare_helpers.js"); + + const replTest = new ReplSetTest({nodes: 1}); + replTest.startSet(); + replTest.initiate(); + + const primary = replTest.getPrimary(); + + const dbName = "test"; + const collName = "commit_prepared_transaction_before_stable_timestamp"; + const testDB = primary.getDB(dbName); + const testColl = testDB.getCollection(collName); + + assert.commandWorked(testDB.runCommand({create: collName})); + + // Make sure there is no lag between the oldest timestamp and the stable timestamp so we can + // test that committing a prepared transaction behind the oldest timestamp succeeds. + assert.commandWorked(primary.adminCommand({ + "configureFailPoint": 'WTSetOldestTSToStableTS', + "mode": 'alwaysOn', + })); + + const session = primary.startSession({causalConsistency: false}); + const sessionDB = session.getDatabase(dbName); + const sessionColl = sessionDB.getCollection(collName); + + session.startTransaction(); + assert.commandWorked(sessionColl.insert({_id: 1})); + const prepareTimestamp = PrepareHelpers.prepareTransaction(session); + + jsTestLog("Do a majority write to advance the stable timestamp past the prepareTimestamp"); + // Doing a majority write after preparing the transaction ensures that the stable timestamp is + // past the prepare timestamp because this write must be in the committed snapshot. + assert.commandWorked( + testColl.runCommand("insert", {documents: [{_id: 2}]}, {writeConcern: {w: "majority"}})); + + jsTestLog("Committing the transaction before the stable timestamp"); + + // Since we have advanced the stableTimestamp to be after the prepareTimestamp, when we commit + // at the prepareTimestamp, we are certain that we are committing behind the stableTimestamp. + assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); + + // Make sure we can see the insert from the prepared transaction. + arrayEq(sessionColl.find().toArray(), [{_id: 1}, {_id: 2}]); + + assert.commandWorked( + primary.adminCommand({configureFailPoint: 'WTSetOldestTSToStableTS', mode: 'off'})); + + replTest.stopSet(); +}());
\ No newline at end of file diff --git a/jstests/replsets/commit_transaction_recovery.js b/jstests/replsets/commit_transaction_recovery.js index 2e0ec6befe8..1f40a13938a 100644 --- a/jstests/replsets/commit_transaction_recovery.js +++ b/jstests/replsets/commit_transaction_recovery.js @@ -42,14 +42,13 @@ // Since the commitTimestamp is after the last snapshot, this oplog entry will be replayed // during replication recovery during restart. - assert.commandWorked(PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); jsTestLog("Restarting node"); // Perform a clean shutdown and restart. Note that the 'disableSnapshotting' failpoint will be // unset on the node following the restart. - replTest.stop(primary, undefined, {skipValidation: true}); - replTest.start(primary, {}, true); + replTest.restart(primary); jsTestLog("Node was restarted"); @@ -66,7 +65,7 @@ // Also, make sure that we can run another transaction after recovery without any problems. assert.commandWorked(sessionDB[collName].update({_id: 1}, {_id: 1, a: 1})); prepareTimestamp = PrepareHelpers.prepareTransaction(session); - assert.commandWorked(PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); assert.eq(testDB[collName].findOne({_id: 1}), {_id: 1, a: 1}); replTest.stopSet(); diff --git a/jstests/replsets/commit_transaction_recovery_data_already_applied.js b/jstests/replsets/commit_transaction_recovery_data_already_applied.js index a6a28b6b726..7e8fd73f4a5 100644 --- a/jstests/replsets/commit_transaction_recovery_data_already_applied.js +++ b/jstests/replsets/commit_transaction_recovery_data_already_applied.js @@ -93,7 +93,7 @@ // Also, make sure that we can run another transaction after recovery without any problems. assert.commandWorked(sessionDB[collName].update({_id: 1}, {_id: 1, a: 1})); prepareTimestamp = PrepareHelpers.prepareTransaction(session); - assert.commandWorked(PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); assert.eq(testDB[collName].findOne({_id: 1}), {_id: 1, a: 1}); replTest.stopSet(); diff --git a/jstests/replsets/commit_transaction_rollback_recovery_data_already_applied.js b/jstests/replsets/commit_transaction_rollback_recovery_data_already_applied.js index a31ad4b17d9..886fa36d501 100644 --- a/jstests/replsets/commit_transaction_rollback_recovery_data_already_applied.js +++ b/jstests/replsets/commit_transaction_rollback_recovery_data_already_applied.js @@ -88,7 +88,7 @@ // Also, make sure that we can run another transaction after recovery without any problems. assert.commandWorked(sessionDB[collName].update({_id: 1}, {_id: 1, a: 1})); prepareTimestamp = PrepareHelpers.prepareTransaction(session); - assert.commandWorked(PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); assert.eq(testDB[collName].findOne({_id: 1}), {_id: 1, a: 1}); diff --git a/jstests/replsets/hang_before_releasing_transaction_oplog_hole.js b/jstests/replsets/hang_before_releasing_transaction_oplog_hole.js index 0ad75de1133..af74be61d60 100644 --- a/jstests/replsets/hang_before_releasing_transaction_oplog_hole.js +++ b/jstests/replsets/hang_before_releasing_transaction_oplog_hole.js @@ -45,7 +45,7 @@ assert.commandWorked(db.adminCommand( {configureFailPoint: 'hangBeforeReleasingTransactionOplogHole', mode: 'alwaysOn'})); - PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp); + PrepareHelpers.commitTransaction(session, prepareTimestamp); } const joinTransaction = startParallelShell(transactionFn, rst.ports[0]); diff --git a/jstests/replsets/initial_sync_commit_prepared_transaction.js b/jstests/replsets/initial_sync_commit_prepared_transaction.js index 270fd3c3f4b..81590fc0bc2 100644 --- a/jstests/replsets/initial_sync_commit_prepared_transaction.js +++ b/jstests/replsets/initial_sync_commit_prepared_transaction.js @@ -77,8 +77,7 @@ // Commit a transaction on the sync source while collection cloning is paused so that we know // they must be applied during the oplog application stage of initial sync. - assert.commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(session1, prepareTimestamp1)); + assert.commandWorked(PrepareHelpers.commitTransaction(session1, prepareTimestamp1)); jsTestLog("Resuming initial sync"); @@ -106,8 +105,7 @@ session2.startTransaction(); assert.commandWorked(sessionColl2.insert({_id: 4})); let prepareTimestamp2 = PrepareHelpers.prepareTransaction(session2); - assert.commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(session2, prepareTimestamp2)); + assert.commandWorked(PrepareHelpers.commitTransaction(session2, prepareTimestamp2)); res = newPrimary.getDB(dbName).getCollection(collName).findOne({_id: 4}); assert.docEq(res, {_id: 4}, res); diff --git a/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp.js b/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp.js index b5509f848c9..cece52cde31 100644 --- a/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp.js +++ b/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp.js @@ -63,9 +63,7 @@ // that since the beginApplyingTimestamp is the timestamp after which operations are applied // during initial sync, this commitTransaction will not be applied. const beginApplyingTimestamp = - assert - .commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(session1, prepareTimestamp1)) + assert.commandWorked(PrepareHelpers.commitTransaction(session1, prepareTimestamp1)) .operationTime; jsTestLog("beginApplyingTimestamp: " + beginApplyingTimestamp); diff --git a/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp_no_oplog_application.js b/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp_no_oplog_application.js index 5d04f468f2c..fe0f0932ff1 100644 --- a/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp_no_oplog_application.js +++ b/jstests/replsets/initial_sync_fetch_from_oldest_active_transaction_timestamp_no_oplog_application.js @@ -68,9 +68,7 @@ // that since the beginApplyingTimestamp is the timestamp after which operations are applied // during initial sync, this commitTransaction will not be applied. const beginApplyingTimestamp = - assert - .commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(session1, prepareTimestamp1)) + assert.commandWorked(PrepareHelpers.commitTransaction(session1, prepareTimestamp1)) .operationTime; jsTestLog("beginApplyingTimestamp/stopTimestamp: " + beginApplyingTimestamp); diff --git a/jstests/replsets/prepare_conflict_read_concern_behavior.js b/jstests/replsets/prepare_conflict_read_concern_behavior.js index 58efe922fa4..4327f7d86c5 100644 --- a/jstests/replsets/prepare_conflict_read_concern_behavior.js +++ b/jstests/replsets/prepare_conflict_read_concern_behavior.js @@ -69,13 +69,11 @@ assert.commandWorked(sessionColl.update({_id: 2}, {_id: 2, in_prepared_txn: true})); const prepareTimestamp = PrepareHelpers.prepareTransaction(session); - // TODO: Once we no longer hold the stable optime behind the earliest prepare optime - // whose corresponding commit/abort oplog entry optime is not majority committed, allow - // this insert to be majority committed. const clusterTimeAfterPrepare = assert - .commandWorked( - testColl.runCommand("insert", {documents: [{_id: 4, in_prepared_txn: false}]})) + .commandWorked(testColl.runCommand( + "insert", + {documents: [{_id: 4, in_prepared_txn: false}], writeConcern: {w: "majority"}})) .operationTime; jsTestLog("prepareTimestamp: " + prepareTimestamp + " clusterTimeBeforePrepare: " + @@ -85,12 +83,9 @@ assert.gt(prepareTimestamp, clusterTimeBeforePrepare); assert.gt(clusterTimeAfterPrepare, prepareTimestamp); - // TODO: Once we no longer hold the stable optime behind the earliest prepare optime - // whose corresponding commit/abort oplog entry optime is not majority committed, uncomment - // this read. - // jsTestLog( - // "Test read with read concern 'majority' doesn't block on a prepared transaction."); - // assert.commandWorked(read({level: 'majority'}, successTimeout, testDB, collName, 2)); + jsTestLog( + "Test read with read concern 'majority' doesn't block on a prepared transaction."); + assert.commandWorked(read({level: 'majority'}, successTimeout, testDB, collName, 3)); jsTestLog("Test read with read concern 'local' doesn't block on a prepared transaction."); assert.commandWorked(read({level: 'local'}, successTimeout, testDB, collName, 3)); @@ -147,13 +142,10 @@ session2.startTransaction( {readConcern: {level: "snapshot", atClusterTime: clusterTimeAfterPrepare}}); - // TODO: Once we no longer hold the stable optime behind the earliest prepare optime - // whose corresponding commit/abort oplog entry optime is not majority committed, uncomment - // this read. - // jsTestLog("Test read with read concern 'snapshot' and a read timestamp after " + - // "prepareTimestamp on non-prepared documents doesn't block on a prepared " + - // "transaction."); - // assert.commandWorked(read({}, failureTimeout, sessionDB2, collName2, 1)); + jsTestLog("Test read with read concern 'snapshot' and a read timestamp after " + + "prepareTimestamp on non-prepared documents doesn't block on a prepared " + + "transaction."); + assert.commandWorked(read({}, failureTimeout, sessionDB2, collName2, 1)); jsTestLog("Test read with read concern 'snapshot' and a read timestamp after " + "prepareTimestamp blocks on a prepared transaction."); diff --git a/jstests/replsets/prepare_transaction_index_build.js b/jstests/replsets/prepare_transaction_index_build.js index 3f657533a09..7f495ddceed 100644 --- a/jstests/replsets/prepare_transaction_index_build.js +++ b/jstests/replsets/prepare_transaction_index_build.js @@ -63,7 +63,7 @@ jsTestLog("Committing txn"); // Commit the transaction. - assert.commandWorked(PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); replTest.awaitReplication(); jsTestLog("Testing index integrity"); diff --git a/jstests/replsets/prepare_transaction_survives_state_transition_to_and_from_recovering.js b/jstests/replsets/prepare_transaction_survives_state_transition_to_and_from_recovering.js index d466ed296ea..fcab1ae7a27 100644 --- a/jstests/replsets/prepare_transaction_survives_state_transition_to_and_from_recovering.js +++ b/jstests/replsets/prepare_transaction_survives_state_transition_to_and_from_recovering.js @@ -52,8 +52,7 @@ jsTestLog("Commiting the second prepared transaction while a node is in the RECOVERING state"); - assert.commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(session2, prepareTimestamp2)); + assert.commandWorked(PrepareHelpers.commitTransaction(session2, prepareTimestamp2)); replSet.awaitReplication(); jsTestLog("Taking secondary out of maintenance mode so it will transition back to SECONDARY"); @@ -96,10 +95,9 @@ jsTestLog("Committing transaction"); - assert.commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(newSession, prepareTimestamp1)); + assert.commandWorked(PrepareHelpers.commitTransaction(newSession, prepareTimestamp1)); replSet.awaitReplication(); replSet.stopSet(); -}());
\ No newline at end of file +}()); diff --git a/jstests/replsets/prepared_transaction_on_failover.js b/jstests/replsets/prepared_transaction_on_failover.js index 18e9fbefdc2..a87abbfc512 100644 --- a/jstests/replsets/prepared_transaction_on_failover.js +++ b/jstests/replsets/prepared_transaction_on_failover.js @@ -58,8 +58,7 @@ // Create a proxy session to reuse the session state of the old primary. const newSession = new _DelegatingDriverSession(newPrimary, session); - assert.commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(newSession, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(newSession, prepareTimestamp)); replTest.awaitReplication(); assert.docEq(doc, testDB.getCollection(collName).findOne()); diff --git a/jstests/replsets/recover_committed_aborted_prepared_transactions.js b/jstests/replsets/recover_committed_aborted_prepared_transactions.js index 4365b54ff1c..561e9e4eb2c 100644 --- a/jstests/replsets/recover_committed_aborted_prepared_transactions.js +++ b/jstests/replsets/recover_committed_aborted_prepared_transactions.js @@ -56,8 +56,7 @@ const prepareTimestamp2 = PrepareHelpers.prepareTransaction(session2); // Commit the first transaction. - assert.commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(session1, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(session1, prepareTimestamp)); // Abort the second transaction. session2.abortTransaction_forTesting(); @@ -112,8 +111,7 @@ assert.commandWorked(sessionColl1.insert({_id: 5})); const prepareTimestamp3 = PrepareHelpers.prepareTransaction(session1); // Make sure we can successfully retry the commitTransaction command after rollback. - assert.commandWorked( - PrepareHelpers.commitTransactionAfterPrepareTS(session1, prepareTimestamp3)); + assert.commandWorked(PrepareHelpers.commitTransaction(session1, prepareTimestamp3)); session1.startTransaction(); assert.commandWorked(sessionColl1.insert({_id: 6})); diff --git a/jstests/replsets/recover_multiple_prepared_transactions_startup.js b/jstests/replsets/recover_multiple_prepared_transactions_startup.js index 21781ce02e4..32fe036da15 100644 --- a/jstests/replsets/recover_multiple_prepared_transactions_startup.js +++ b/jstests/replsets/recover_multiple_prepared_transactions_startup.js @@ -152,7 +152,7 @@ session.startTransaction(); assert.commandWorked(sessionDB[collName].update({_id: 1}, {_id: 1, a: 3})); prepareTimestamp = PrepareHelpers.prepareTransaction(session); - assert.commandWorked(PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp)); + assert.commandWorked(PrepareHelpers.commitTransaction(session, prepareTimestamp)); assert.eq(testDB[collName].findOne({_id: 1}), {_id: 1, a: 3}); replTest.stopSet(); diff --git a/jstests/replsets/recover_prepared_transaction_state.js b/jstests/replsets/recover_prepared_transaction_state.js index fd6d630c819..e78e68169ec 100644 --- a/jstests/replsets/recover_prepared_transaction_state.js +++ b/jstests/replsets/recover_prepared_transaction_state.js @@ -77,7 +77,7 @@ // The following commit and abort will be rolled back. rollbackTest.transitionToRollbackOperations(); - PrepareHelpers.commitTransactionAfterPrepareTS(session1, prepareTimestamp); + PrepareHelpers.commitTransaction(session1, prepareTimestamp); session2.abortTransaction_forTesting(); // The fastcount should be accurate because there are no open transactions. diff --git a/jstests/replsets/rollback_aborted_prepared_transaction.js b/jstests/replsets/rollback_aborted_prepared_transaction.js index bd7e3057105..3093582aede 100644 --- a/jstests/replsets/rollback_aborted_prepared_transaction.js +++ b/jstests/replsets/rollback_aborted_prepared_transaction.js @@ -79,7 +79,7 @@ session.startTransaction(); assert.commandWorked(sessionColl.insert({_id: 1})); const prepareTimestamp = PrepareHelpers.prepareTransaction(session); - PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp); + PrepareHelpers.commitTransaction(session, prepareTimestamp); assert.eq(testColl.find().itcount(), 2); assert.eq(testColl.count(), 2); diff --git a/jstests/replsets/rollback_via_refetch_commit_transaction.js b/jstests/replsets/rollback_via_refetch_commit_transaction.js index 8f51dcdfedf..bb4ca534553 100644 --- a/jstests/replsets/rollback_via_refetch_commit_transaction.js +++ b/jstests/replsets/rollback_via_refetch_commit_transaction.js @@ -50,7 +50,7 @@ TestData.skipCheckDBHashes = true; session.getDatabase('admin').adminCommand({prepareTransaction: 1, writeConcern: {w: 1}})); assert(result.prepareTimestamp, "prepareTransaction did not return a 'prepareTimestamp': " + tojson(result)); - PrepareHelpers.commitTransactionAfterPrepareTS(session, result.prepareTimestamp); + PrepareHelpers.commitTransaction(session, result.prepareTimestamp); // Step down current primary and elect a node that lacks the commit. rollbackTest.transitionToSyncSourceOperationsBeforeRollback(); diff --git a/jstests/replsets/rollover_preserves_active_txns.js b/jstests/replsets/rollover_preserves_active_txns.js index e6743c5f25a..8597d1aa3cc 100644 --- a/jstests/replsets/rollover_preserves_active_txns.js +++ b/jstests/replsets/rollover_preserves_active_txns.js @@ -83,7 +83,7 @@ if (commitOrAbort === "commit") { jsTestLog("Commit prepared transaction and wait for oplog to shrink to max oplogSize"); - PrepareHelpers.commitTransactionAfterPrepareTS(session, prepareTimestamp); + PrepareHelpers.commitTransaction(session, prepareTimestamp); } else if (commitOrAbort === "abort") { jsTestLog("Abort prepared transaction and wait for oplog to shrink to max oplogSize"); session.abortTransaction_forTesting(); |