What to do when “Optimistic Locking” doesn't work?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












I have this following scenario:



  1. User makes GET request to /projects/1 and receives an ETag

  2. User makes PUT request to /projects/1 with ETag from step #1

  3. User makes another PUT request to /projects/1 with ETag from step #1

Normally, the second PUT request would receive a 412 response, since the ETag is now stale - the first PUT request modified the resource, so the ETag doesn't match anymore.



But what if the 2 PUT requests are sent at the same time (or exactly one after the other)? The first PUT request does not have time to process and update the resource before PUT #2 arrives, which causes PUT #2 to overwrite PUT #1. The whole point of "Optimistic Locking" is for that not to happen...










share|improve this question





















  • Atomize your operations in business-level transactions, as Esben explains below.
    – Robert Harvey
    1 hour ago











  • What would happen if I atomized my operations using transactions? PUT #2 would not be processed until PUT #1 is fully processed?
    – maximedupre
    48 mins ago
















up vote
4
down vote

favorite












I have this following scenario:



  1. User makes GET request to /projects/1 and receives an ETag

  2. User makes PUT request to /projects/1 with ETag from step #1

  3. User makes another PUT request to /projects/1 with ETag from step #1

Normally, the second PUT request would receive a 412 response, since the ETag is now stale - the first PUT request modified the resource, so the ETag doesn't match anymore.



But what if the 2 PUT requests are sent at the same time (or exactly one after the other)? The first PUT request does not have time to process and update the resource before PUT #2 arrives, which causes PUT #2 to overwrite PUT #1. The whole point of "Optimistic Locking" is for that not to happen...










share|improve this question





















  • Atomize your operations in business-level transactions, as Esben explains below.
    – Robert Harvey
    1 hour ago











  • What would happen if I atomized my operations using transactions? PUT #2 would not be processed until PUT #1 is fully processed?
    – maximedupre
    48 mins ago












up vote
4
down vote

favorite









up vote
4
down vote

favorite











I have this following scenario:



  1. User makes GET request to /projects/1 and receives an ETag

  2. User makes PUT request to /projects/1 with ETag from step #1

  3. User makes another PUT request to /projects/1 with ETag from step #1

Normally, the second PUT request would receive a 412 response, since the ETag is now stale - the first PUT request modified the resource, so the ETag doesn't match anymore.



But what if the 2 PUT requests are sent at the same time (or exactly one after the other)? The first PUT request does not have time to process and update the resource before PUT #2 arrives, which causes PUT #2 to overwrite PUT #1. The whole point of "Optimistic Locking" is for that not to happen...










share|improve this question













I have this following scenario:



  1. User makes GET request to /projects/1 and receives an ETag

  2. User makes PUT request to /projects/1 with ETag from step #1

  3. User makes another PUT request to /projects/1 with ETag from step #1

Normally, the second PUT request would receive a 412 response, since the ETag is now stale - the first PUT request modified the resource, so the ETag doesn't match anymore.



But what if the 2 PUT requests are sent at the same time (or exactly one after the other)? The first PUT request does not have time to process and update the resource before PUT #2 arrives, which causes PUT #2 to overwrite PUT #1. The whole point of "Optimistic Locking" is for that not to happen...







rest language-agnostic concurrency http






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 1 hour ago









maximedupre

2455




2455











  • Atomize your operations in business-level transactions, as Esben explains below.
    – Robert Harvey
    1 hour ago











  • What would happen if I atomized my operations using transactions? PUT #2 would not be processed until PUT #1 is fully processed?
    – maximedupre
    48 mins ago
















  • Atomize your operations in business-level transactions, as Esben explains below.
    – Robert Harvey
    1 hour ago











  • What would happen if I atomized my operations using transactions? PUT #2 would not be processed until PUT #1 is fully processed?
    – maximedupre
    48 mins ago















Atomize your operations in business-level transactions, as Esben explains below.
– Robert Harvey
1 hour ago





Atomize your operations in business-level transactions, as Esben explains below.
– Robert Harvey
1 hour ago













What would happen if I atomized my operations using transactions? PUT #2 would not be processed until PUT #1 is fully processed?
– maximedupre
48 mins ago




What would happen if I atomized my operations using transactions? PUT #2 would not be processed until PUT #1 is fully processed?
– maximedupre
48 mins ago










4 Answers
4






active

oldest

votes

















up vote
5
down vote













The ETag mechanism specifies only the communication protocol for optimistic locking. It's the responsibility of the application to implement the mechanism to detect concurrent updates to enforce the optimistic lock.



In a typical application that uses a database, you'd usually do this by opening a transaction when processing a PUT request. You'd normally read the existing state of the database inside that transaction (to gain a read lock), check your Etag validity, and overwrite the data (in a way that'll cause a write conflict when there's any incompatible concurrent transaction), then commit. If you setup the transaction correctly, then one of the commits should fail because they'll both be trying to update the same data concurrently. You'll then be able to use this transaction failure to either return 412 or retry the request, if it makes sense for the application.






share|improve this answer




















  • The way the server currently implements the mechanism to detect concurrent updates is by comparing hashes of the resource. The server also use transactions for all operations, but I’m not acquiring any locks, which might be what causes the problem. However in your example, how can there be an error in one of the commits if the transactions are using locks? The second transaction should be pending when reading the state, until the first transaction resolves.
    – maximedupre
    49 mins ago










  • @maximedupre: if you are using transaction, you have some sort of locks, though it may be implicit locks (the locks are acquired automatically when you read/update fields rather than explicitly requested). The mechanism I described above can be implemented using just those implicit locking. As your other question, it depends on the database that you're using, but many modern databases uses MVCC (multi version concurrency control) to allow multiple readers and writer to work on the same fields without unnecessarily blocking each other.
    – Lie Ryan
    36 mins ago


















up vote
1
down vote













In that case the service is broken. It should utilize transactions or locks or databases that have this functionality out of the box.






share|improve this answer




















  • This reads more like a comment.
    – Greg Burghardt
    1 hour ago

















up vote
0
down vote













It's on the application developer to actually check the E-Tag and provide that logic. It's not magic that the web server does for you because it only knows how to calculate E-Tag headers for static content. So let's take your scenario above and break down how the interaction should happen.



GET /projects/1


Server receives the request, determines the E-Tag for this version of the record, returning that with the actual content.



200 - OK
E-Tag: "412"
Content-Type: application/json
modified: false


Since the client now has the E-Tag value, it can include that with the PUT request:



PUT /projects/1
E-Tag: "412"
Content-Type: application/json
modified: true


At this point your application has to do the following:



  • Verify that the E-Tag is still correct: "412" == "412" ?

  • If so, make the update and calculate a new E-Tag

Send the success response.



204 No Content
E-Tag: "543"


If another request comes and attempts to perform a PUT similar to the request above, the second time your server code evaluates it, you are responsible to provide the error message.



  • Verify the E-Tag is still correct: "412" != "543"

On failure, send the failure response.



412 Precondition Failed


This is code you actually have to write. The E-Tag can in fact be any text (within the limits defined in the HTTP spec). It doesn't have to be a number. It can be a hash value as well.






share|improve this answer



























    up vote
    0
    down vote













    You have to execute the following pair atomically:



    • checking of the tag for validity (i.e. is up to date)

    • updating the resource

    Others are calling this a transaction — but fundamentally, the atomic execution of these two operations is what prevents one from overwriting the other by accident of timing; without this you have a race condition, as you're noting.



    This is still considered optimistic locking, if you look at the big picture: that the resource itself is not locked by the initial read (GET) by any User or any Users who are looking at the data, whether with intent to update or not.



    Some atomic behavior is necessary, but this happens within a single request (the PUT) rather than attempting to hold a lock over multiple network interactions; this is optimistic locking: the object is not locked by the GET yet still can be updated by PUT.



    There are also many ways to achieve atomic execution of these two operations — locking the resource is not the only option; for example, a lightweight thread lock may suffice and depends on you're application's execution context.





    share




















      Your Answer







      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "131"
      ;
      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: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f379506%2fwhat-to-do-when-optimistic-locking-doesnt-work%23new-answer', 'question_page');

      );

      Post as a guest






























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      5
      down vote













      The ETag mechanism specifies only the communication protocol for optimistic locking. It's the responsibility of the application to implement the mechanism to detect concurrent updates to enforce the optimistic lock.



      In a typical application that uses a database, you'd usually do this by opening a transaction when processing a PUT request. You'd normally read the existing state of the database inside that transaction (to gain a read lock), check your Etag validity, and overwrite the data (in a way that'll cause a write conflict when there's any incompatible concurrent transaction), then commit. If you setup the transaction correctly, then one of the commits should fail because they'll both be trying to update the same data concurrently. You'll then be able to use this transaction failure to either return 412 or retry the request, if it makes sense for the application.






      share|improve this answer




















      • The way the server currently implements the mechanism to detect concurrent updates is by comparing hashes of the resource. The server also use transactions for all operations, but I’m not acquiring any locks, which might be what causes the problem. However in your example, how can there be an error in one of the commits if the transactions are using locks? The second transaction should be pending when reading the state, until the first transaction resolves.
        – maximedupre
        49 mins ago










      • @maximedupre: if you are using transaction, you have some sort of locks, though it may be implicit locks (the locks are acquired automatically when you read/update fields rather than explicitly requested). The mechanism I described above can be implemented using just those implicit locking. As your other question, it depends on the database that you're using, but many modern databases uses MVCC (multi version concurrency control) to allow multiple readers and writer to work on the same fields without unnecessarily blocking each other.
        – Lie Ryan
        36 mins ago















      up vote
      5
      down vote













      The ETag mechanism specifies only the communication protocol for optimistic locking. It's the responsibility of the application to implement the mechanism to detect concurrent updates to enforce the optimistic lock.



      In a typical application that uses a database, you'd usually do this by opening a transaction when processing a PUT request. You'd normally read the existing state of the database inside that transaction (to gain a read lock), check your Etag validity, and overwrite the data (in a way that'll cause a write conflict when there's any incompatible concurrent transaction), then commit. If you setup the transaction correctly, then one of the commits should fail because they'll both be trying to update the same data concurrently. You'll then be able to use this transaction failure to either return 412 or retry the request, if it makes sense for the application.






      share|improve this answer




















      • The way the server currently implements the mechanism to detect concurrent updates is by comparing hashes of the resource. The server also use transactions for all operations, but I’m not acquiring any locks, which might be what causes the problem. However in your example, how can there be an error in one of the commits if the transactions are using locks? The second transaction should be pending when reading the state, until the first transaction resolves.
        – maximedupre
        49 mins ago










      • @maximedupre: if you are using transaction, you have some sort of locks, though it may be implicit locks (the locks are acquired automatically when you read/update fields rather than explicitly requested). The mechanism I described above can be implemented using just those implicit locking. As your other question, it depends on the database that you're using, but many modern databases uses MVCC (multi version concurrency control) to allow multiple readers and writer to work on the same fields without unnecessarily blocking each other.
        – Lie Ryan
        36 mins ago













      up vote
      5
      down vote










      up vote
      5
      down vote









      The ETag mechanism specifies only the communication protocol for optimistic locking. It's the responsibility of the application to implement the mechanism to detect concurrent updates to enforce the optimistic lock.



      In a typical application that uses a database, you'd usually do this by opening a transaction when processing a PUT request. You'd normally read the existing state of the database inside that transaction (to gain a read lock), check your Etag validity, and overwrite the data (in a way that'll cause a write conflict when there's any incompatible concurrent transaction), then commit. If you setup the transaction correctly, then one of the commits should fail because they'll both be trying to update the same data concurrently. You'll then be able to use this transaction failure to either return 412 or retry the request, if it makes sense for the application.






      share|improve this answer












      The ETag mechanism specifies only the communication protocol for optimistic locking. It's the responsibility of the application to implement the mechanism to detect concurrent updates to enforce the optimistic lock.



      In a typical application that uses a database, you'd usually do this by opening a transaction when processing a PUT request. You'd normally read the existing state of the database inside that transaction (to gain a read lock), check your Etag validity, and overwrite the data (in a way that'll cause a write conflict when there's any incompatible concurrent transaction), then commit. If you setup the transaction correctly, then one of the commits should fail because they'll both be trying to update the same data concurrently. You'll then be able to use this transaction failure to either return 412 or retry the request, if it makes sense for the application.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered 1 hour ago









      Lie Ryan

      6,02811824




      6,02811824











      • The way the server currently implements the mechanism to detect concurrent updates is by comparing hashes of the resource. The server also use transactions for all operations, but I’m not acquiring any locks, which might be what causes the problem. However in your example, how can there be an error in one of the commits if the transactions are using locks? The second transaction should be pending when reading the state, until the first transaction resolves.
        – maximedupre
        49 mins ago










      • @maximedupre: if you are using transaction, you have some sort of locks, though it may be implicit locks (the locks are acquired automatically when you read/update fields rather than explicitly requested). The mechanism I described above can be implemented using just those implicit locking. As your other question, it depends on the database that you're using, but many modern databases uses MVCC (multi version concurrency control) to allow multiple readers and writer to work on the same fields without unnecessarily blocking each other.
        – Lie Ryan
        36 mins ago

















      • The way the server currently implements the mechanism to detect concurrent updates is by comparing hashes of the resource. The server also use transactions for all operations, but I’m not acquiring any locks, which might be what causes the problem. However in your example, how can there be an error in one of the commits if the transactions are using locks? The second transaction should be pending when reading the state, until the first transaction resolves.
        – maximedupre
        49 mins ago










      • @maximedupre: if you are using transaction, you have some sort of locks, though it may be implicit locks (the locks are acquired automatically when you read/update fields rather than explicitly requested). The mechanism I described above can be implemented using just those implicit locking. As your other question, it depends on the database that you're using, but many modern databases uses MVCC (multi version concurrency control) to allow multiple readers and writer to work on the same fields without unnecessarily blocking each other.
        – Lie Ryan
        36 mins ago
















      The way the server currently implements the mechanism to detect concurrent updates is by comparing hashes of the resource. The server also use transactions for all operations, but I’m not acquiring any locks, which might be what causes the problem. However in your example, how can there be an error in one of the commits if the transactions are using locks? The second transaction should be pending when reading the state, until the first transaction resolves.
      – maximedupre
      49 mins ago




      The way the server currently implements the mechanism to detect concurrent updates is by comparing hashes of the resource. The server also use transactions for all operations, but I’m not acquiring any locks, which might be what causes the problem. However in your example, how can there be an error in one of the commits if the transactions are using locks? The second transaction should be pending when reading the state, until the first transaction resolves.
      – maximedupre
      49 mins ago












      @maximedupre: if you are using transaction, you have some sort of locks, though it may be implicit locks (the locks are acquired automatically when you read/update fields rather than explicitly requested). The mechanism I described above can be implemented using just those implicit locking. As your other question, it depends on the database that you're using, but many modern databases uses MVCC (multi version concurrency control) to allow multiple readers and writer to work on the same fields without unnecessarily blocking each other.
      – Lie Ryan
      36 mins ago





      @maximedupre: if you are using transaction, you have some sort of locks, though it may be implicit locks (the locks are acquired automatically when you read/update fields rather than explicitly requested). The mechanism I described above can be implemented using just those implicit locking. As your other question, it depends on the database that you're using, but many modern databases uses MVCC (multi version concurrency control) to allow multiple readers and writer to work on the same fields without unnecessarily blocking each other.
      – Lie Ryan
      36 mins ago













      up vote
      1
      down vote













      In that case the service is broken. It should utilize transactions or locks or databases that have this functionality out of the box.






      share|improve this answer




















      • This reads more like a comment.
        – Greg Burghardt
        1 hour ago














      up vote
      1
      down vote













      In that case the service is broken. It should utilize transactions or locks or databases that have this functionality out of the box.






      share|improve this answer




















      • This reads more like a comment.
        – Greg Burghardt
        1 hour ago












      up vote
      1
      down vote










      up vote
      1
      down vote









      In that case the service is broken. It should utilize transactions or locks or databases that have this functionality out of the box.






      share|improve this answer












      In that case the service is broken. It should utilize transactions or locks or databases that have this functionality out of the box.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered 1 hour ago









      Esben Skov Pedersen

      2,61711217




      2,61711217











      • This reads more like a comment.
        – Greg Burghardt
        1 hour ago
















      • This reads more like a comment.
        – Greg Burghardt
        1 hour ago















      This reads more like a comment.
      – Greg Burghardt
      1 hour ago




      This reads more like a comment.
      – Greg Burghardt
      1 hour ago










      up vote
      0
      down vote













      It's on the application developer to actually check the E-Tag and provide that logic. It's not magic that the web server does for you because it only knows how to calculate E-Tag headers for static content. So let's take your scenario above and break down how the interaction should happen.



      GET /projects/1


      Server receives the request, determines the E-Tag for this version of the record, returning that with the actual content.



      200 - OK
      E-Tag: "412"
      Content-Type: application/json
      modified: false


      Since the client now has the E-Tag value, it can include that with the PUT request:



      PUT /projects/1
      E-Tag: "412"
      Content-Type: application/json
      modified: true


      At this point your application has to do the following:



      • Verify that the E-Tag is still correct: "412" == "412" ?

      • If so, make the update and calculate a new E-Tag

      Send the success response.



      204 No Content
      E-Tag: "543"


      If another request comes and attempts to perform a PUT similar to the request above, the second time your server code evaluates it, you are responsible to provide the error message.



      • Verify the E-Tag is still correct: "412" != "543"

      On failure, send the failure response.



      412 Precondition Failed


      This is code you actually have to write. The E-Tag can in fact be any text (within the limits defined in the HTTP spec). It doesn't have to be a number. It can be a hash value as well.






      share|improve this answer
























        up vote
        0
        down vote













        It's on the application developer to actually check the E-Tag and provide that logic. It's not magic that the web server does for you because it only knows how to calculate E-Tag headers for static content. So let's take your scenario above and break down how the interaction should happen.



        GET /projects/1


        Server receives the request, determines the E-Tag for this version of the record, returning that with the actual content.



        200 - OK
        E-Tag: "412"
        Content-Type: application/json
        modified: false


        Since the client now has the E-Tag value, it can include that with the PUT request:



        PUT /projects/1
        E-Tag: "412"
        Content-Type: application/json
        modified: true


        At this point your application has to do the following:



        • Verify that the E-Tag is still correct: "412" == "412" ?

        • If so, make the update and calculate a new E-Tag

        Send the success response.



        204 No Content
        E-Tag: "543"


        If another request comes and attempts to perform a PUT similar to the request above, the second time your server code evaluates it, you are responsible to provide the error message.



        • Verify the E-Tag is still correct: "412" != "543"

        On failure, send the failure response.



        412 Precondition Failed


        This is code you actually have to write. The E-Tag can in fact be any text (within the limits defined in the HTTP spec). It doesn't have to be a number. It can be a hash value as well.






        share|improve this answer






















          up vote
          0
          down vote










          up vote
          0
          down vote









          It's on the application developer to actually check the E-Tag and provide that logic. It's not magic that the web server does for you because it only knows how to calculate E-Tag headers for static content. So let's take your scenario above and break down how the interaction should happen.



          GET /projects/1


          Server receives the request, determines the E-Tag for this version of the record, returning that with the actual content.



          200 - OK
          E-Tag: "412"
          Content-Type: application/json
          modified: false


          Since the client now has the E-Tag value, it can include that with the PUT request:



          PUT /projects/1
          E-Tag: "412"
          Content-Type: application/json
          modified: true


          At this point your application has to do the following:



          • Verify that the E-Tag is still correct: "412" == "412" ?

          • If so, make the update and calculate a new E-Tag

          Send the success response.



          204 No Content
          E-Tag: "543"


          If another request comes and attempts to perform a PUT similar to the request above, the second time your server code evaluates it, you are responsible to provide the error message.



          • Verify the E-Tag is still correct: "412" != "543"

          On failure, send the failure response.



          412 Precondition Failed


          This is code you actually have to write. The E-Tag can in fact be any text (within the limits defined in the HTTP spec). It doesn't have to be a number. It can be a hash value as well.






          share|improve this answer












          It's on the application developer to actually check the E-Tag and provide that logic. It's not magic that the web server does for you because it only knows how to calculate E-Tag headers for static content. So let's take your scenario above and break down how the interaction should happen.



          GET /projects/1


          Server receives the request, determines the E-Tag for this version of the record, returning that with the actual content.



          200 - OK
          E-Tag: "412"
          Content-Type: application/json
          modified: false


          Since the client now has the E-Tag value, it can include that with the PUT request:



          PUT /projects/1
          E-Tag: "412"
          Content-Type: application/json
          modified: true


          At this point your application has to do the following:



          • Verify that the E-Tag is still correct: "412" == "412" ?

          • If so, make the update and calculate a new E-Tag

          Send the success response.



          204 No Content
          E-Tag: "543"


          If another request comes and attempts to perform a PUT similar to the request above, the second time your server code evaluates it, you are responsible to provide the error message.



          • Verify the E-Tag is still correct: "412" != "543"

          On failure, send the failure response.



          412 Precondition Failed


          This is code you actually have to write. The E-Tag can in fact be any text (within the limits defined in the HTTP spec). It doesn't have to be a number. It can be a hash value as well.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 38 mins ago









          Berin Loritsch

          32.4k562129




          32.4k562129




















              up vote
              0
              down vote













              You have to execute the following pair atomically:



              • checking of the tag for validity (i.e. is up to date)

              • updating the resource

              Others are calling this a transaction — but fundamentally, the atomic execution of these two operations is what prevents one from overwriting the other by accident of timing; without this you have a race condition, as you're noting.



              This is still considered optimistic locking, if you look at the big picture: that the resource itself is not locked by the initial read (GET) by any User or any Users who are looking at the data, whether with intent to update or not.



              Some atomic behavior is necessary, but this happens within a single request (the PUT) rather than attempting to hold a lock over multiple network interactions; this is optimistic locking: the object is not locked by the GET yet still can be updated by PUT.



              There are also many ways to achieve atomic execution of these two operations — locking the resource is not the only option; for example, a lightweight thread lock may suffice and depends on you're application's execution context.





              share
























                up vote
                0
                down vote













                You have to execute the following pair atomically:



                • checking of the tag for validity (i.e. is up to date)

                • updating the resource

                Others are calling this a transaction — but fundamentally, the atomic execution of these two operations is what prevents one from overwriting the other by accident of timing; without this you have a race condition, as you're noting.



                This is still considered optimistic locking, if you look at the big picture: that the resource itself is not locked by the initial read (GET) by any User or any Users who are looking at the data, whether with intent to update or not.



                Some atomic behavior is necessary, but this happens within a single request (the PUT) rather than attempting to hold a lock over multiple network interactions; this is optimistic locking: the object is not locked by the GET yet still can be updated by PUT.



                There are also many ways to achieve atomic execution of these two operations — locking the resource is not the only option; for example, a lightweight thread lock may suffice and depends on you're application's execution context.





                share






















                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  You have to execute the following pair atomically:



                  • checking of the tag for validity (i.e. is up to date)

                  • updating the resource

                  Others are calling this a transaction — but fundamentally, the atomic execution of these two operations is what prevents one from overwriting the other by accident of timing; without this you have a race condition, as you're noting.



                  This is still considered optimistic locking, if you look at the big picture: that the resource itself is not locked by the initial read (GET) by any User or any Users who are looking at the data, whether with intent to update or not.



                  Some atomic behavior is necessary, but this happens within a single request (the PUT) rather than attempting to hold a lock over multiple network interactions; this is optimistic locking: the object is not locked by the GET yet still can be updated by PUT.



                  There are also many ways to achieve atomic execution of these two operations — locking the resource is not the only option; for example, a lightweight thread lock may suffice and depends on you're application's execution context.





                  share












                  You have to execute the following pair atomically:



                  • checking of the tag for validity (i.e. is up to date)

                  • updating the resource

                  Others are calling this a transaction — but fundamentally, the atomic execution of these two operations is what prevents one from overwriting the other by accident of timing; without this you have a race condition, as you're noting.



                  This is still considered optimistic locking, if you look at the big picture: that the resource itself is not locked by the initial read (GET) by any User or any Users who are looking at the data, whether with intent to update or not.



                  Some atomic behavior is necessary, but this happens within a single request (the PUT) rather than attempting to hold a lock over multiple network interactions; this is optimistic locking: the object is not locked by the GET yet still can be updated by PUT.



                  There are also many ways to achieve atomic execution of these two operations — locking the resource is not the only option; for example, a lightweight thread lock may suffice and depends on you're application's execution context.






                  share











                  share


                  share










                  answered 1 min ago









                  Erik Eidt

                  20.8k33052




                  20.8k33052



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f379506%2fwhat-to-do-when-optimistic-locking-doesnt-work%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Comments

                      Popular posts from this blog

                      Long meetings (6-7 hours a day): Being “babysat” by supervisor

                      What does second last employer means? [closed]

                      One-line joke