summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbdul Qadeer <abdul.qadeer@mongodb.com>2022-08-02 14:27:38 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-08-04 16:24:48 +0000
commit89bc2f7533ecf43dd57c413b40066928e4c24e24 (patch)
treeb80b31325c4986573fbd3f35eea3f76007555637
parentc500300c081eab9bbf42dccff05a0588cfc59821 (diff)
downloadmongo-89bc2f7533ecf43dd57c413b40066928e4c24e24.tar.gz
SERVER-67492 Skip updating txn table for op=n when o2 is empty
(cherry picked from commit 3f6c0845204161336f052d3665817ad5adc1a1b5)
-rw-r--r--etc/backports_required_for_multiversion_tests.yml4
-rw-r--r--jstests/sharding/move_chunk_interrupt_postimage.js42
-rw-r--r--src/mongo/db/repl/session_update_tracker.cpp3
-rw-r--r--src/mongo/db/s/session_catalog_migration_destination.cpp15
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