summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorCheahuychou Mao <mao.cheahuychou@gmail.com>2022-02-03 06:18:15 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-02-03 07:19:42 +0000
commit71287a3a8f033923ca9c2735c72da4460fbbf06d (patch)
tree16b9482e36180928ca9a3a4dd7b8d8384ecc55ac /src/mongo
parent1d8aaed7f9286ce90317d03fc1815bb58b43e31d (diff)
downloadmongo-71287a3a8f033923ca9c2735c72da4460fbbf06d.tar.gz
SERVER-60524 Make retryable internal transactions retryable across data placement changes
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp1
-rw-r--r--src/mongo/db/commands/write_commands.cpp3
-rw-r--r--src/mongo/db/ops/write_ops.idl12
-rw-r--r--src/mongo/db/ops/write_ops_exec.cpp3
-rw-r--r--src/mongo/db/ops/write_ops_exec.h4
5 files changed, 23 insertions, 0 deletions
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 6518620c51c..dab13fcc40c 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -645,6 +645,7 @@ write_ops::FindAndModifyCommandReply CmdFindAndModify::Invocation::typedRun(
RetryableWritesStats::get(opCtx)->incrementRetriedCommandsCount();
RetryableWritesStats::get(opCtx)->incrementRetriedStatementsCount();
auto findAndModifyReply = parseOplogEntryForFindAndModify(opCtx, req, *entry);
+ findAndModifyReply.setRetriedStmtId(stmtId);
// Make sure to wait for writeConcern on the opTime that will include this
// write. Needs to set to the system last opTime to get the latest term in an
diff --git a/src/mongo/db/commands/write_commands.cpp b/src/mongo/db/commands/write_commands.cpp
index e90d4ac25ce..865a69dbc7b 100644
--- a/src/mongo/db/commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands.cpp
@@ -458,6 +458,9 @@ void populateReply(OperationContext* opCtx,
auto& replyBase = cmdReply->getWriteCommandReplyBase();
replyBase.setN(nVal);
+ if (!result.retriedStmtIds.empty()) {
+ replyBase.setRetriedStmtIds(result.retriedStmtIds);
+ }
if (!errors.empty()) {
replyBase.setWriteErrors(errors);
diff --git a/src/mongo/db/ops/write_ops.idl b/src/mongo/db/ops/write_ops.idl
index 91c82db928b..cf58747c7c5 100644
--- a/src/mongo/db/ops/write_ops.idl
+++ b/src/mongo/db/ops/write_ops.idl
@@ -91,6 +91,12 @@ structs:
type: array<object_owned>
optional: true
unstable: false
+ retriedStmtIds:
+ description: "The statement numbers for the write statements that had already been
+ executed, thus were not executed by this command."
+ type: array<int>
+ optional: true
+ unstable: true
InsertCommandReply:
description: "Contains information related to insert command reply."
@@ -298,6 +304,12 @@ structs:
description: "The document after the write, if the 'new' field of the request is
true. Otherwise, the document before the write."
unstable: false
+ retriedStmtId:
+ description: "The statement number for this findAndModify statement if it had
+ already been executed, thus was not executed by this command."
+ type: int
+ optional: true
+ unstable: true
commands:
diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp
index 32213015ea7..748c70da401 100644
--- a/src/mongo/db/ops/write_ops_exec.cpp
+++ b/src/mongo/db/ops/write_ops_exec.cpp
@@ -724,6 +724,7 @@ WriteResult performInserts(OperationContext* opCtx,
} else if (wasAlreadyExecuted) {
containsRetry = true;
RetryableWritesStats::get(opCtx)->incrementRetriedStatementsCount();
+ out.retriedStmtIds.push_back(stmtId);
out.results.emplace_back(makeWriteResultForInsertOrDeleteRetry());
}
}
@@ -1022,6 +1023,7 @@ WriteResult performUpdates(OperationContext* opCtx,
containsRetry = true;
RetryableWritesStats::get(opCtx)->incrementRetriedStatementsCount();
out.results.emplace_back(parseOplogEntryForUpdate(*entry));
+ out.retriedStmtIds.push_back(stmtId);
continue;
}
}
@@ -1247,6 +1249,7 @@ WriteResult performDeletes(OperationContext* opCtx,
containsRetry = true;
RetryableWritesStats::get(opCtx)->incrementRetriedStatementsCount();
out.results.emplace_back(makeWriteResultForInsertOrDeleteRetry());
+ out.retriedStmtIds.push_back(stmtId);
continue;
}
diff --git a/src/mongo/db/ops/write_ops_exec.h b/src/mongo/db/ops/write_ops_exec.h
index 377a440524f..548a3034713 100644
--- a/src/mongo/db/ops/write_ops_exec.h
+++ b/src/mongo/db/ops/write_ops_exec.h
@@ -56,6 +56,10 @@ struct WriteResult {
*/
std::vector<StatusWith<SingleWriteResult>> results;
+ // Stores the statement ids for the ops that had already been executed, thus were not executed
+ // by this write.
+ std::vector<StmtId> retriedStmtIds;
+
// In case of an error, whether the operation can continue.
bool canContinue = true;
};