[SERVER-41766] Secondary may encounter prepare conflict when applying write that sets the multikey flag Created: 14/Jun/19 Updated: 29/Oct/23 Resolved: 27/Jun/19 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Replication |
| Affects Version/s: | 4.2.0-rc0 |
| Fix Version/s: | 4.2.0-rc3, 4.3.1 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | William Schultz (Inactive) | Assignee: | William Schultz (Inactive) |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Attachments: |
|
||||||||||||||||||||||||||||||||||||
| Issue Links: |
|
||||||||||||||||||||||||||||||||||||
| Backwards Compatibility: | Fully Compatible | ||||||||||||||||||||||||||||||||||||
| Operating System: | ALL | ||||||||||||||||||||||||||||||||||||
| Backport Requested: |
v4.2
|
||||||||||||||||||||||||||||||||||||
| Sprint: | Repl 2019-07-01 | ||||||||||||||||||||||||||||||||||||
| Participants: | |||||||||||||||||||||||||||||||||||||
| Linked BF Score: | 19 | ||||||||||||||||||||||||||||||||||||
| Description |
|
There is a divergence around how we deal with setting the multikey flag on primary versus secondary. On primary, we go through this codepath, and we register an onCommit handler on the OperationContext to switch the in-memory multikey bit to true, which means we won't set it until the prepared transaction commits. So, that allows subsequent writes to try updating the multikey flag again, since they see that the bit is not set. These writes would hit a prepare conflict on the collection catalog entry document and block, which is OK. On secondary, however, when we apply a prepared transaction, we appear to set the in-memory multikey bit immediately, instead of waiting for the prepared transaction to commit, since the OperationContext we use here doesn't appear to be correlated to the actual transaction we applied and the WUOW commits right away. Because of this behavior divergence, the following scenario, with two nodes, n0 and n1, is possible:
The attached repro ( multikey_prepare_txns.js |
| Comments |
| Comment by Githook User [ 12/Aug/19 ] |
|
Author: {'name': 'William Schultz', 'email': 'william.schultz@mongodb.com', 'username': 'will62794'}Message: Now that we update the multikey flag within a transaction in a side transaction, the in-memory state about the multikey write will be naturally visible to subsequent writes inside the transaction, so we don't need to keep around any extra structures to enforce this anymore. |
| Comment by Githook User [ 02/Jul/19 ] |
|
Author: {'name': 'William Schultz', 'username': 'will62794', 'email': 'william.schultz@mongodb.com'}Message: When a write inside a multi-document transaction needs to set an index as multikey, we update the multikey flag in the on-disk catalog in a transaction separate from the parent transaction. We commit this side transaction immediately, so as to avoid the catalog write generating prepare conflicts if it was written as part of a parent transaction that later became prepared. In general, it is safe to set an index as multikey too early. The multikey write is timestamped at the most recent value of the LogicalClock. (cherry picked from commit 3147f5e1c37546b817934ef892d5e353170a9935) |
| Comment by William Schultz (Inactive) [ 01/Jul/19 ] |
|
Additional notes from discussion on this ticket: Within a multi-document transaction, reads should be able to see the effect of previous writes done within that transaction. If a previous write in a transaction has set the index to be multikey, then a subsequent read must know that fact in order to return correct results. This is true in general for multikey writes. After this change, we update the multikey flag in memory and on-disk as soon as we do such a write inside a transaction. We do not wait for the transaction to commit. Thus, transactions should be able to read their own multikey writes correctly, without any extra logic. |
| Comment by Githook User [ 27/Jun/19 ] |
|
Author: {'name': 'William Schultz', 'email': 'william.schultz@mongodb.com', 'username': 'will62794'}Message: When a write inside a multi-document transaction needs to set an index as multikey, we update the multikey flag in the on-disk catalog in a transaction separate from the parent transaction. We commit this side transaction immediately, so as to avoid the catalog write generating prepare conflicts if it was written as part of a parent transaction that later became prepared. In general, it is safe to set an index as multikey too early. The multikey write is timestamped at the most recent value of the LogicalClock. |