diff options
author | Abdul Qadeer <abdul.qadeer@mongodb.com> | 2022-08-02 14:27:38 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-08-04 16:24:48 +0000 |
commit | 89bc2f7533ecf43dd57c413b40066928e4c24e24 (patch) | |
tree | b80b31325c4986573fbd3f35eea3f76007555637 | |
parent | c500300c081eab9bbf42dccff05a0588cfc59821 (diff) | |
download | mongo-89bc2f7533ecf43dd57c413b40066928e4c24e24.tar.gz |
SERVER-67492 Skip updating txn table for op=n when o2 is empty
(cherry picked from commit 3f6c0845204161336f052d3665817ad5adc1a1b5)
4 files changed, 61 insertions, 3 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml index 49b64477434..24de22869ec 100644 --- a/etc/backports_required_for_multiversion_tests.yml +++ b/etc/backports_required_for_multiversion_tests.yml @@ -238,6 +238,8 @@ last-continuous: test_file: jstests/aggregation/match_no_swap_rand.js - ticket: SERVER-63049 test_file: jstests/noPassthrough/operator_counters_accumulators.js + - ticket: SERVER-67492 + test_file: jstests/sharding/move_chunk_interrupt_postimage.js # Tests that should only be excluded from particular suites should be listed under that suite. suites: @@ -609,6 +611,8 @@ last-lts: test_file: jstests/replsets/optime.js - ticket: SERVER-66072 test_file: jstests/aggregation/match_no_swap_rand.js + - ticket: SERVER-67492 + test_file: jstests/sharding/move_chunk_interrupt_postimage.js # Tests that should only be excluded from particular suites should be listed under that suite. suites: diff --git a/jstests/sharding/move_chunk_interrupt_postimage.js b/jstests/sharding/move_chunk_interrupt_postimage.js new file mode 100644 index 00000000000..69537bb9ce0 --- /dev/null +++ b/jstests/sharding/move_chunk_interrupt_postimage.js @@ -0,0 +1,42 @@ +/** + * Tests that chunk migration interruption before processing post/pre image oplog entry leads + * to consistent config.transactions data across primary and secondaries (SERVER-67492) + */ + +(function() { +"use strict"; + +load("jstests/sharding/libs/create_sharded_collection_util.js"); +load("jstests/libs/fail_point_util.js"); +load('jstests/libs/parallel_shell_helpers.js'); + +const st = new ShardingTest({mongos: 1, config: 1, shards: 2, rs: {nodes: 2}}); +const interruptBeforeProcessingPrePostImageOriginatingOpFP = + configureFailPoint(st.rs1.getPrimary(), "interruptBeforeProcessingPrePostImageOriginatingOp"); + +const collection = st.s.getCollection("test.mycoll"); +CreateShardedCollectionUtil.shardCollectionWithChunks(collection, {x: 1}, [ + {min: {x: MinKey}, max: {x: 0}, shard: st.shard0.shardName}, + {min: {x: 0}, max: {x: 100}, shard: st.shard0.shardName}, + {min: {x: 100}, max: {x: MaxKey}, shard: st.shard1.shardName}, +]); + +assert.commandWorked(collection.insert({_id: 0, x: 10})); +assert.commandWorked(collection.runCommand("findAndModify", { + query: {x: 10}, + update: {$set: {y: 2}}, + new: true, + txnNumber: NumberLong(1), +})); + +const res = st.s.adminCommand({ + moveChunk: collection.getFullName(), + find: {x: 10}, + to: st.shard1.shardName, +}); +assert.commandFailedWithCode(res, ErrorCodes.CommandFailed); +interruptBeforeProcessingPrePostImageOriginatingOpFP.wait(); + +interruptBeforeProcessingPrePostImageOriginatingOpFP.off(); +st.stop(); +})(); diff --git a/src/mongo/db/repl/session_update_tracker.cpp b/src/mongo/db/repl/session_update_tracker.cpp index 87c12cf5463..aa5f55e01e5 100644 --- a/src/mongo/db/repl/session_update_tracker.cpp +++ b/src/mongo/db/repl/session_update_tracker.cpp @@ -34,6 +34,7 @@ #include "mongo/db/repl/session_update_tracker.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/ops/write_ops_retryability.h" #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/server_options.h" #include "mongo/db/session.h" @@ -212,7 +213,7 @@ boost::optional<std::vector<OplogEntry>> SessionUpdateTracker::_updateSessionInf return {}; } - if (!entry.getObject2()) { + if (!entry.getObject2() || entry.getObject2()->isEmpty()) { return {}; } } diff --git a/src/mongo/db/s/session_catalog_migration_destination.cpp b/src/mongo/db/s/session_catalog_migration_destination.cpp index f00a2215460..07339c079a1 100644 --- a/src/mongo/db/s/session_catalog_migration_destination.cpp +++ b/src/mongo/db/s/session_catalog_migration_destination.cpp @@ -58,6 +58,8 @@ namespace mongo { namespace { +MONGO_FAIL_POINT_DEFINE(interruptBeforeProcessingPrePostImageOriginatingOp); + const auto kOplogField = "oplog"; const WriteConcernOptions kMajorityWC(WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, @@ -491,10 +493,19 @@ void SessionCatalogMigrationDestination::_retrieveSessionStateFromSource(Service lastOpTimeWaited = lastResult.oplogTime; } } + for (BSONArrayIteratorSorted oplogIter(oplogArray); oplogIter.more();) { + auto oplogEntry = oplogIter.next().Obj(); + interruptBeforeProcessingPrePostImageOriginatingOp.executeIf( + [&](const auto&) { + uasserted(6749200, + "Intentionally failing session migration before processing post/pre " + "image originating update oplog entry"); + }, + [&](const auto&) { return !oplogEntry["needsRetryImage"].eoo(); }); try { - lastResult = processSessionOplog( - oplogIter.next().Obj(), lastResult, service, _cancellationToken); + lastResult = + processSessionOplog(oplogEntry, lastResult, service, _cancellationToken); } catch (const ExceptionFor<ErrorCodes::TransactionTooOld>&) { // This means that the server has a newer txnNumber than the oplog being // migrated, so just skip it |