summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLingzhi Deng <lingzhi.deng@mongodb.com>2021-05-25 20:02:41 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-25 20:39:56 +0000
commitf1cb4b059ba3fe4d82d44ad480f08acb02697a99 (patch)
tree6646b936348c45ddf0aa7ec469d382c080f79220 /src
parentc09e27d0ea8b535a3a766924c141116c801f641a (diff)
downloadmongo-f1cb4b059ba3fe4d82d44ad480f08acb02697a99.tar.gz
SERVER-57098: Reset retryable write state on the tenant migration recipient if it is starting a new history chain
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/repl/tenant_oplog_applier.cpp38
1 files changed, 29 insertions, 9 deletions
diff --git a/src/mongo/db/repl/tenant_oplog_applier.cpp b/src/mongo/db/repl/tenant_oplog_applier.cpp
index dd8b69ec271..d3a02d2b8eb 100644
--- a/src/mongo/db/repl/tenant_oplog_applier.cpp
+++ b/src/mongo/db/repl/tenant_oplog_applier.cpp
@@ -727,15 +727,6 @@ void TenantOplogApplier::_writeSessionNoOpsForRange(
boost::none /* autocommit */,
boost::none /* startTransaction */);
- // We should never process the same donor statement twice, except in failover
- // cases where we'll also have "forgotten" the statement was executed.
- uassert(5350902,
- str::stream() << "Tenant oplog application processed same retryable write "
- "twice for transaction "
- << txnNumber << " statement " << entryStmtIds.front()
- << " on session " << sessionId,
- !txnParticipant.checkStatementExecutedNoOplogEntryFetch(entryStmtIds.front()));
-
// We could have an existing lastWriteOpTime for the same retryable write chain from a
// previously aborted migration. This could also happen if the tenant being migrated has
// previously resided in this replica set. So we want to start a new history chain
@@ -746,8 +737,37 @@ void TenantOplogApplier::_writeSessionNoOpsForRange(
prevWriteOpTime = txnParticipant.getLastWriteOpTime();
} else {
prevWriteOpTime = OpTime();
+
+ // Before we start a new history chain, reset the in-memory retryable write
+ // state in the txnParticipant so it can be built up from scratch again with
+ // the new chain.
+ LOGV2_DEBUG(5709800,
+ 2,
+ "Tenant oplog applier resetting existing retryable write state",
+ "lastWriteOpTime"_attr = txnParticipant.getLastWriteOpTime(),
+ "_cloneFinishedRecipientOpTime"_attr = _cloneFinishedRecipientOpTime,
+ "sessionId"_attr = sessionId,
+ "txnNumber"_attr = txnNumber,
+ "statementIds"_attr = entryStmtIds,
+ "tenant"_attr = _tenantId,
+ "migrationUuid"_attr = _migrationUuid);
+ txnParticipant.invalidate(opCtx.get());
+ txnParticipant.refreshFromStorageIfNeededNoOplogEntryFetch(opCtx.get());
+ txnParticipant.beginOrContinue(opCtx.get(),
+ txnNumber,
+ boost::none /* autocommit */,
+ boost::none /* startTransaction */);
}
+ // We should never process the same donor statement twice, except in failover
+ // cases where we'll also have "forgotten" the statement was executed.
+ uassert(5350902,
+ str::stream() << "Tenant oplog application processed same retryable write "
+ "twice for transaction "
+ << txnNumber << " statement " << entryStmtIds.front()
+ << " on session " << sessionId,
+ !txnParticipant.checkStatementExecutedNoOplogEntryFetch(entryStmtIds.front()));
+
// Set sessionId, txnNumber, and statementId for all ops in a retryable write.
noopEntry.setSessionId(sessionId);
noopEntry.setTxnNumber(txnNumber);