<!-- 
RSS generated by JIRA (9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66) at Thu Feb 08 05:01:12 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>MongoDB Jira</title>
    <link>https://jira.mongodb.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>9.7.1</version>
        <build-number>970001</build-number>
        <build-date>13-04-2023</build-date>
    </build-info>


<item>
            <title>[SERVER-42699] Server should perform majority write concern no-op write before returning TransientTransactionError label on commitTransaction cmd.</title>
                <link>https://jira.mongodb.org/browse/SERVER-42699</link>
                <project id="10000" key="SERVER">Core Server</project>
                    <description>&lt;p&gt;For replica set transaction, we can get into double committing problem for below scenario (see SPEC-1185).&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;1) The driver is connected to a replica set where node A is primary.&lt;br/&gt;
 2) The driver sends commitTransaction to A with w:1. A commits the transaction but dies before it can reply. This constitutes a retryable error, which means the driver can retry the commitTransaction command.&lt;br/&gt;
 3) Node B is briefly elected.&lt;br/&gt;
 4) The driver retries commitTransaction on B, and B replies with an error label TransientTransactionError (TTE). This implies that the driver may retry the entire transaction. (To be noted, driver always retry the commitTransaction with {w: majority}).&lt;br/&gt;
 5) Node A revives before B has done any w:majority writes and gets reelected as primary. The driver then retries the entire transaction on A where it commits successfully. This leads to &lt;b&gt;double committing problem&lt;/b&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Currently TTE label is attached to the following error codes.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;ErrorCodes::NoSuchTransaction&lt;/li&gt;
	&lt;li&gt;ErrorCodes::WriteConflict&lt;/li&gt;
	&lt;li&gt;ErrorCodes::LockTimeout&lt;/li&gt;
	&lt;li&gt;ErrorCodes::PreparedTransactionInProgress&lt;/li&gt;
	&lt;li&gt;&#160;&lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/base/error_codes.err#L358&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;Snapshot Error&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/base/error_codes.err#L340&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;Retargetting Error&lt;/a&gt; - ***&lt;b&gt;&lt;font color=&quot;#403294&quot;&gt;Doesn&apos;t apply to replica set transaction&lt;/font&gt;&lt;/b&gt;*** (Correct me if I am wrong).&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;But, only for ErrorCodes::NoSuchTransaction, we &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/service_entry_point_common.cpp#L546-L550&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;perform no-op writes &lt;/a&gt; w/ {w: majority} and &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/base/transaction_error.cpp#L52-L55&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;check the write concern error to attach TTE label&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Its safe now not to do majority write concern no-op writes for other error codes which can generate TTE label. Because, we currently perform below sequence of steps for commitTransaction cmd (for unprepared transactions/ single replica sets).&lt;br/&gt;
 Seq #1&#160; If session option doesn&apos;t contain &quot;startTransaction&quot;, do&#160;&lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/transaction_participant.cpp#L509-L511&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;_continueMultiDocumentTransaction()&lt;/a&gt;&#160;.&lt;br/&gt;
 &lt;font color=&quot;#de350b&quot;&gt;&lt;b&gt;/&lt;/b&gt;** TTE error codes from 2- 5 is possible only from here onwards ****&lt;b&gt;/&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;
 Seq #2 Else, execute&#160; _beginMultiDocumentTransaction() - starts a new transaction with next higher txn number.&lt;br/&gt;
 Seq #3&#160;&lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/transaction_participant.cpp#L943&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;Unstash&lt;/a&gt; the transaction lock resources. &lt;br/&gt;
 Seq #4 Abort the unprepared transaction if seq#3 fails. Else proceed to seq #5.&lt;br/&gt;
 Seq #5&#160;&lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/service_entry_point_common.cpp#L428&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;Run&lt;/a&gt; the (commit) command.&#160;&lt;br/&gt;
 Seq #6&#160; If step 3 fails, then &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/service_entry_point_common.cpp#L424&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;abort the unprepared transaction&lt;/a&gt;. Else, &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/service_entry_point_common.cpp#L465&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;stash the transaction lock resources&lt;/a&gt; only if they are not committed or aborted.&lt;br/&gt;
 &#160;&lt;/p&gt;

&lt;p&gt;To be noted, commitTxn cmd can&apos;t contain &apos;startTransaction&apos;. So, it should always go to _continueMultiDocumentTransaction().&lt;br/&gt;
 According to me,&#160;there can be only 2 cases&lt;br/&gt;
 Case #1 Node B has already committed the transaction via secondary oplog application. And, then the driver retries the commitTransaction on node B.&lt;br/&gt;
 &#160; &#160;- This &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/transaction_participant.cpp#L954-L957&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;won&apos;t&lt;/a&gt; even go to unstash step (seq #3) as there is nothing to unstash. So, it&apos;s impossible to return TTE error codes. ( I am assuming that the sessions are all single threaded).&lt;br/&gt;
 Case #2 Node B has not received/applied the commitTransaction oplog entry. And, then the driver retries the commitTransaction on node B.&lt;br/&gt;
 &#160; &#160;- This can only generate &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/transaction_participant.cpp#L408&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;NoSuchTransaction&lt;/a&gt; Error code.&lt;/p&gt;

&lt;p&gt;The system won&apos;t be safe, if we get any TTE label error codes from 2 thru 5 (ErrorCodes::WriteConflict to Snapshot error) before seq #1 beginOrContinue() (i.e. _continueMultiDocumentTransaction()).&#160; This means we should perform no-op writes {w:majority} and check for majority write concern error before attaching the TTE label for all TTE error codes. Performing no-op writes always has a performance cost. So, instead we should try to strengthen the contract of TTE label itself.&lt;/p&gt;

&lt;p&gt;Note: For Cross-shard transaction, the txn coordinator doesn&apos;t care about TTE label attached to the commitTransaction cmd response.&lt;/p&gt;</description>
                <environment></environment>
        <key id="887279">SERVER-42699</key>
            <summary>Server should perform majority write concern no-op write before returning TransientTransactionError label on commitTransaction cmd.</summary>
                <type id="3" iconUrl="https://jira.mongodb.org/secure/viewavatar?size=xsmall&amp;avatarId=14718&amp;avatarType=issuetype">Task</type>
                                            <priority id="3" iconUrl="https://jira.mongodb.org/images/icons/priorities/major.svg">Major - P3</priority>
                        <status id="6" iconUrl="https://jira.mongodb.org/images/icons/statuses/closed.png" description="The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.">Closed</status>
                    <statusCategory id="3" key="done" colorName="success"/>
                                    <resolution id="2">Won&apos;t Fix</resolution>
                                        <assignee username="tess.avitabile@mongodb.com">Tess Avitabile</assignee>
                                    <reporter username="suganthi.mani@mongodb.com">Suganthi Mani</reporter>
                        <labels>
                    </labels>
                <created>Thu, 8 Aug 2019 12:14:23 +0000</created>
                <updated>Tue, 10 Dec 2019 16:58:35 +0000</updated>
                            <resolved>Tue, 10 Dec 2019 16:58:35 +0000</resolved>
                                                                    <component>Replication</component>
                                        <votes>0</votes>
                                    <watches>3</watches>
                                                                                                                <comments>
                            <comment id="2366388" author="suganthi.mani" created="Mon, 12 Aug 2019 11:57:08 +0000"  >&lt;p&gt;My proposal for TTE error label to be safe to retry the entire transaction from beginning is that,&#160;before sending TTE label response for commitTransaction cmd, we should make sure we perform one of 2 things:&lt;/p&gt;

&lt;p&gt;1) For active txn (i.e. txn number matches the &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/transaction_participant.h#L913&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;current active txn number&lt;/a&gt;), we should abort the transaction implicitly if it&apos;s not aborted previously.&lt;br/&gt;
 2) For inactive txn (i.e. txn number doesn&apos;t match the &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/transaction_participant.h#L913&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;current active txn number&lt;/a&gt;), we should make sure the transaction will be rolled back eventually if it was previously committed.&lt;/p&gt;

&lt;p&gt;Only for case#2, we would require to perform a majority write concern no-op (only if the write concern supplied with cmd was kMajority). Otherwise, its safe to send the TTE label response w/o no-op write.&lt;/p&gt;

&lt;p&gt;Note: Currently in our code, NoSuchTransaction error code is thrown in &lt;a href=&quot;https://github.com/mongodb/mongo/blob/f14d9c4c07e69c2109de0af059123060c73cdd77/src/mongo/db/transaction_participant.cpp#L427-L434&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;cases&lt;/a&gt; where we don&apos;t require no-op write.&lt;/p&gt;

&lt;p&gt;CC &lt;a href=&quot;https://jira.mongodb.org/secure/ViewProfile.jspa?name=esha.maharishi&quot; class=&quot;user-hover&quot; rel=&quot;esha.maharishi&quot;&gt;esha.maharishi&lt;/a&gt;&#160;&lt;a href=&quot;https://jira.mongodb.org/secure/ViewProfile.jspa?name=shane.harvey&quot; class=&quot;user-hover&quot; rel=&quot;shane.harvey&quot;&gt;shane.harvey&lt;/a&gt;&lt;br/&gt;
 And, tagging &lt;a href=&quot;https://jira.mongodb.org/secure/ViewProfile.jspa?name=siyuan.zhou&quot; class=&quot;user-hover&quot; rel=&quot;siyuan.zhou&quot;&gt;siyuan.zhou&lt;/a&gt; if anything needed to considered for large transactions &amp;gt; 16MB.&lt;/p&gt;</comment>
                            <comment id="2362742" author="judah.schvimer" created="Thu, 8 Aug 2019 13:12:51 +0000"  >&lt;p&gt;&lt;a href=&quot;https://jira.mongodb.org/secure/ViewProfile.jspa?name=suganthi.mani&quot; class=&quot;user-hover&quot; rel=&quot;suganthi.mani&quot;&gt;suganthi.mani&lt;/a&gt;, should we also abort a transaction whenever we return a TTE error label?&lt;/p&gt;</comment>
                    </comments>
                    <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                <customfield id="customfield_10050" key="com.atlassian.jira.toolkit:comments">
                        <customfieldname># Replies</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>2.0</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_18555" key="com.onresolve.jira.groovy.groovyrunner:scripted-field">
                        <customfieldname># of Sprints</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>1.0</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10055" key="com.atlassian.jira.ext.charting:firstresponsedate">
                        <customfieldname>Date of 1st Reply</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>Thu, 8 Aug 2019 13:12:51 +0000</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10052" key="com.atlassian.jira.toolkit:dayslastcommented">
                        <customfieldname>Days since reply</customfieldname>
                        <customfieldvalues>
                                        4 years, 26 weeks, 2 days ago
    
                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_18254" key="com.onresolve.jira.groovy.groovyrunner:scripted-field">
                        <customfieldname>Dependencies</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue><![CDATA[]]></customfieldvalue>


                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_15850" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        <customfield id="customfield_10057" key="com.atlassian.jira.toolkit:lastusercommented">
                        <customfieldname>Last comment by Customer</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>true</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                            <customfield id="customfield_10056" key="com.atlassian.jira.toolkit:lastupdaterorcommenter">
                        <customfieldname>Last commenter</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>tess.avitabile@mongodb.com</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_11151" key="com.atlassian.jira.toolkit:LastCommentDate">
                        <customfieldname>Last public comment date</customfieldname>
                        <customfieldvalues>
                            4 years, 26 weeks, 2 days ago
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                    <customfield id="customfield_10051" key="com.atlassian.jira.toolkit:participants">
                        <customfieldname>Participants</customfieldname>
                        <customfieldvalues>
                                        <customfieldvalue>judah.schvimer@mongodb.com</customfieldvalue>
            <customfieldvalue>suganthi.mani@mongodb.com</customfieldvalue>
            <customfieldvalue>tess.avitabile@mongodb.com</customfieldvalue>
    
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                        <customfield id="customfield_14254" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Product Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>1|hvji13:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                <customfield id="customfield_12550" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>2|hvs57j:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10558" key="com.pyxis.greenhopper.jira:gh-global-rank">
                        <customfieldname>Rank (Obsolete)</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>9223372036854775807</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                            <customfield id="customfield_23361" key="com.onresolve.jira.groovy.groovyrunner:scripted-field">
                        <customfieldname>Requested By</customfieldname>
                        <customfieldvalues>
                                

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                        <customfield id="customfield_10557" key="com.pyxis.greenhopper.jira:gh-sprint">
                        <customfieldname>Sprint</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue id="3438">Repl 2019-12-30</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                            <customfield id="customfield_10053" key="com.atlassian.jira.ext.charting:timeinstatus">
                        <customfieldname>Time In Status</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        <customfield id="customfield_22870" key="com.onresolve.jira.groovy.groovyrunner:scripted-field">
                        <customfieldname>Triagers</customfieldname>
                        <customfieldvalues>
                                

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_14350" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>serverRank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>1|hvj4af:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                    </customfields>
    </item>
</channel>
</rss>