How does MongoDB deal with transactional conflicts?











up vote
1
down vote

favorite












If both two threads do read and write a same document:



try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
result = collection.find(clientSession, keyOfDoc);
if (result blah blah blah) {
// Change the doc
collection.insertOne(clientSession, doc);
}
clientSession.commitTransaction();
}


From the purpose of the transaction, one of the thread should get the edited version of another thread.



However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.



Another situation is the write-write conflict.



try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
collection.insertOne(clientSession, docDifferent);
collection.insertOne(clientSession, docSame);
clientSession.commitTransaction();
}


Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.



What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?










share|improve this question




























    up vote
    1
    down vote

    favorite












    If both two threads do read and write a same document:



    try (ClientSession clientSession = client.startSession()) {
    clientSession.startTransaction();
    result = collection.find(clientSession, keyOfDoc);
    if (result blah blah blah) {
    // Change the doc
    collection.insertOne(clientSession, doc);
    }
    clientSession.commitTransaction();
    }


    From the purpose of the transaction, one of the thread should get the edited version of another thread.



    However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.



    Another situation is the write-write conflict.



    try (ClientSession clientSession = client.startSession()) {
    clientSession.startTransaction();
    collection.insertOne(clientSession, docDifferent);
    collection.insertOne(clientSession, docSame);
    clientSession.commitTransaction();
    }


    Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.



    What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?










    share|improve this question


























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      If both two threads do read and write a same document:



      try (ClientSession clientSession = client.startSession()) {
      clientSession.startTransaction();
      result = collection.find(clientSession, keyOfDoc);
      if (result blah blah blah) {
      // Change the doc
      collection.insertOne(clientSession, doc);
      }
      clientSession.commitTransaction();
      }


      From the purpose of the transaction, one of the thread should get the edited version of another thread.



      However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.



      Another situation is the write-write conflict.



      try (ClientSession clientSession = client.startSession()) {
      clientSession.startTransaction();
      collection.insertOne(clientSession, docDifferent);
      collection.insertOne(clientSession, docSame);
      clientSession.commitTransaction();
      }


      Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.



      What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?










      share|improve this question















      If both two threads do read and write a same document:



      try (ClientSession clientSession = client.startSession()) {
      clientSession.startTransaction();
      result = collection.find(clientSession, keyOfDoc);
      if (result blah blah blah) {
      // Change the doc
      collection.insertOne(clientSession, doc);
      }
      clientSession.commitTransaction();
      }


      From the purpose of the transaction, one of the thread should get the edited version of another thread.



      However, when both threads start transaction they both acquired a read lock, and then read the doc. Both the threads got the old version of the doc. and when they need to write the doc, they try to acquire write locks, which will make the transaction not atomic.



      Another situation is the write-write conflict.



      try (ClientSession clientSession = client.startSession()) {
      clientSession.startTransaction();
      collection.insertOne(clientSession, docDifferent);
      collection.insertOne(clientSession, docSame);
      clientSession.commitTransaction();
      }


      Both thread first acquires write locks of different documents, and then they acquire the write lock of the same document, as it is another transactional conflict.



      What level of lock does MongoDB use? I know they use instance level before version 2.2 while transactions are supported since 4.0. If MongoDB doesn't use database level locks, How does MongoDB deal with transactional conflicts? Or if it uses database level locks, how does it deal with read-write conflicts?







      mongodb concurrency locking






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 8 at 6:25

























      asked Nov 8 at 6:11









      iry

      234




      234
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote













          I found some references in the MongoDB Manual that solved my own question.




          What type of locking does MongoDB use?



          MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).




          MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.




          Restricted Operations



          The following operations are not allowed in multi-document transactions:





          • Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.




            The listCollections and listIndexes commands and their helper methods are also excluded.




          • Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.





          For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.




          Retry Transaction



          The individual write operations inside the
          transaction are not retryable, regardless of whether retryWrites is
          set to true.



          If an operation encounters an error, the returned error may have an
          errorLabels array field. If the error is a transient error, the
          errorLabels array field contains "TransientTransactionError" as an
          element and the transaction as a whole can be retried.




          Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.



          You can simply use this method(modified from the manual example):



          public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
          while (true) {
          try {
          return transactional.call();
          } catch (MongoException ex) {
          if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
          }
          }
          }


          See editions for more languages in the manual ;)!





          References



          Transactions — MongoDB Manual



          FAQ: Concurrency — MongoDB Manual






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53202345%2fhow-does-mongodb-deal-with-transactional-conflicts%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            I found some references in the MongoDB Manual that solved my own question.




            What type of locking does MongoDB use?



            MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).




            MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.




            Restricted Operations



            The following operations are not allowed in multi-document transactions:





            • Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.




              The listCollections and listIndexes commands and their helper methods are also excluded.




            • Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.





            For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.




            Retry Transaction



            The individual write operations inside the
            transaction are not retryable, regardless of whether retryWrites is
            set to true.



            If an operation encounters an error, the returned error may have an
            errorLabels array field. If the error is a transient error, the
            errorLabels array field contains "TransientTransactionError" as an
            element and the transaction as a whole can be retried.




            Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.



            You can simply use this method(modified from the manual example):



            public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
            while (true) {
            try {
            return transactional.call();
            } catch (MongoException ex) {
            if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
            }
            }
            }


            See editions for more languages in the manual ;)!





            References



            Transactions — MongoDB Manual



            FAQ: Concurrency — MongoDB Manual






            share|improve this answer

























              up vote
              0
              down vote













              I found some references in the MongoDB Manual that solved my own question.




              What type of locking does MongoDB use?



              MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).




              MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.




              Restricted Operations



              The following operations are not allowed in multi-document transactions:





              • Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.




                The listCollections and listIndexes commands and their helper methods are also excluded.




              • Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.





              For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.




              Retry Transaction



              The individual write operations inside the
              transaction are not retryable, regardless of whether retryWrites is
              set to true.



              If an operation encounters an error, the returned error may have an
              errorLabels array field. If the error is a transient error, the
              errorLabels array field contains "TransientTransactionError" as an
              element and the transaction as a whole can be retried.




              Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.



              You can simply use this method(modified from the manual example):



              public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
              while (true) {
              try {
              return transactional.call();
              } catch (MongoException ex) {
              if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
              }
              }
              }


              See editions for more languages in the manual ;)!





              References



              Transactions — MongoDB Manual



              FAQ: Concurrency — MongoDB Manual






              share|improve this answer























                up vote
                0
                down vote










                up vote
                0
                down vote









                I found some references in the MongoDB Manual that solved my own question.




                What type of locking does MongoDB use?



                MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).




                MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.




                Restricted Operations



                The following operations are not allowed in multi-document transactions:





                • Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.




                  The listCollections and listIndexes commands and their helper methods are also excluded.




                • Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.





                For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.




                Retry Transaction



                The individual write operations inside the
                transaction are not retryable, regardless of whether retryWrites is
                set to true.



                If an operation encounters an error, the returned error may have an
                errorLabels array field. If the error is a transient error, the
                errorLabels array field contains "TransientTransactionError" as an
                element and the transaction as a whole can be retried.




                Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.



                You can simply use this method(modified from the manual example):



                public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
                while (true) {
                try {
                return transactional.call();
                } catch (MongoException ex) {
                if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
                }
                }
                }


                See editions for more languages in the manual ;)!





                References



                Transactions — MongoDB Manual



                FAQ: Concurrency — MongoDB Manual






                share|improve this answer












                I found some references in the MongoDB Manual that solved my own question.




                What type of locking does MongoDB use?



                MongoDB uses multi-granularity locking 1 that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).




                MongoDB uses multiple levels of locking from collection, database, then to global. However, though it supports multiple levels of locking, the only level you can access is the collection level, meaning you can't create or drop databases or collections in transactions. It also means that acquiring one document to be locked in a collection will cause the whole collection to get locked.




                Restricted Operations



                The following operations are not allowed in multi-document transactions:





                • Operations that affect the database catalog, such as creating or dropping a collection or an index. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection.




                  The listCollections and listIndexes commands and their helper methods are also excluded.




                • Non-CRUD and non-informational operations, such as createUser,getParameter, count, etc. and their helpers.





                For solving conflicts, MongoDB sends error messages to the visitor that could not get the lock when conflict happens.




                Retry Transaction



                The individual write operations inside the
                transaction are not retryable, regardless of whether retryWrites is
                set to true.



                If an operation encounters an error, the returned error may have an
                errorLabels array field. If the error is a transient error, the
                errorLabels array field contains "TransientTransactionError" as an
                element and the transaction as a whole can be retried.




                Meaning when the visitor receive MongoException and the exception .hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL), the visitor should close the session, and REDO the transaction. The visitor should redo and recommit until the commit successes.



                You can simply use this method(modified from the manual example):



                public static <T> T transactWithRetry(Callable<T> transactional) throws Exception {
                while (true) {
                try {
                return transactional.call();
                } catch (MongoException ex) {
                if (!ex.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) throw ex;
                }
                }
                }


                See editions for more languages in the manual ;)!





                References



                Transactions — MongoDB Manual



                FAQ: Concurrency — MongoDB Manual







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 9 at 5:12









                iry

                234




                234






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53202345%2fhow-does-mongodb-deal-with-transactional-conflicts%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Academy of Television Arts & Sciences

                    L'Équipe

                    1995 France bombings