[SERVER-60469] Retryable deletes reserve two optimes for preImage chaining despite not capturing a preImage Created: 05/Oct/21  Updated: 29/Oct/23  Resolved: 12/Oct/21

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 5.2.0, 5.0.4, 5.1.0-rc1

Type: Bug Priority: Blocker - P1
Reporter: Daniel Gottlieb (Inactive) Assignee: Jason Chan
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Backports
Depends
Related
related to SERVER-58740 Reserve multiple oplog slots when wri... Closed
Backwards Compatibility: Fully Compatible
Operating System: ALL
Backport Requested:
v5.1, v5.0
Sprint: Repl 2021-10-18
Participants:
Linked BF Score: 120

 Description   

Traditionally, retryable findAndModify calls reconstruct a response to a retry by writing the returned document to the oplog separate from the update/delete the findAndModify performed.

PM-2213 offers a second option, the document being returned can be written to a separate image collection. However, for features such as tenant migrations and resharding, these images are communicated via the oplog (as opposed to selectively copying that collection).

To accomplish that, we reserve two oplog timestamps when recording an image as part of a findAndModify. This allows us to add an aggregation stage that can seamlessly insert the image into the oplog and not worry about choosing a timestamp.

For regular update findAndModify's, we're (correctly) only reserving two optimes when we intend to store an image.

However, deletes are done unconditionally (i.e: regular retryable deletes don't record a preImage, but do reserve two optimes). This has been identified as a perf regression.

A sample patch that corrects the perf regression:

diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index 3de0a60632..5786026d33 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1157,7 +1161,10 @@ void CollectionImpl::deleteDocument(OperationContext* opCtx,
         uasserted(10089, "cannot remove from a capped collection");
     }
 
-    const auto oplogSlot = reserveOplogSlotsForRetryableFindAndModify(opCtx);
+    boost::optional<OplogSlot> oplogSlot = boost::none;
+    if (storeDeletedDoc == Collection::StoreDeletedDoc::On) {
+        oplogSlot = reserveOplogSlotsForRetryableFindAndModify(opCtx);
+    }
     OpObserver::OplogDeleteEntryArgs deleteArgs{
         nullptr, fromMigrate, getRecordPreImages(), oplogSlot, oplogSlot != boost::none};
 



 Comments   
Comment by Githook User [ 19/Oct/21 ]

Author:

{'name': 'Jason Chan', 'email': 'jason.chan@mongodb.com', 'username': 'jasonjhchan'}

Message: SERVER-60469 Fix bug where two optimes for being reserved for retryable deletes despite not capturing a preImage

(cherry picked from commit 3953546c3cb0afa6dcafbc02f9c732d26a3166ec)
Branch: v5.0
https://github.com/mongodb/mongo/commit/11f126e2c53e0ddf70659456a56a1479cde3d3f8

Comment by Githook User [ 15/Oct/21 ]

Author:

{'name': 'Jason Chan', 'email': 'jason.chan@mongodb.com', 'username': 'jasonjhchan'}

Message: SERVER-60469 Fix bug where two optimes for being reserved for retryable deletes despite not capturing a preImage

(cherry picked from commit 3953546c3cb0afa6dcafbc02f9c732d26a3166ec)
Branch: v5.1
https://github.com/mongodb/mongo/commit/51e4800e88a0284811fad098a7f125ecef835b07

Comment by Githook User [ 12/Oct/21 ]

Author:

{'name': 'Jason Chan', 'email': 'jason.chan@mongodb.com', 'username': 'jasonjhchan'}

Message: SERVER-60469 Fix bug where two optimes for being reserved for retryable deletes despite not capturing a preImage
Branch: master
https://github.com/mongodb/mongo/commit/3953546c3cb0afa6dcafbc02f9c732d26a3166ec

Generated at Thu Feb 08 05:49:53 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.