diff options
author | Lingzhi Deng <lingzhi.deng@mongodb.com> | 2021-05-25 20:02:41 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-25 20:39:56 +0000 |
commit | f1cb4b059ba3fe4d82d44ad480f08acb02697a99 (patch) | |
tree | 6646b936348c45ddf0aa7ec469d382c080f79220 /src | |
parent | c09e27d0ea8b535a3a766924c141116c801f641a (diff) | |
download | mongo-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.cpp | 38 |
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); |