3 Replies Latest reply on Sep 20, 2005 4:22 PM by belaban

    Transactional behavior when creating new nodes

    dpinkney

      Hello,
      First, thanks for putting this great project out.

      I have a question regarding transaction behavior when creating new nodes. I'm trying to figure out how to atomically create a node and update it within a single transaction. Using a REPEATABLE_READ transaction level, the assertion on line 8 below fails if node "/a/b" does not exist - is this expected?

      The behavior I was expecting is that one of the transactions would throw an exception on commit, such that only one transaction modified the node. If node "/a/b/" exists at the start, then thread 2 will get an exception trying to upgrade the read lock on line 6.

       T1 T2
      1 tx1.begin()
      2 tx2.begin()
      3 get("/a/b", "foo") get("/a/b", "foo")
      4 put("/a/b", "foo", "bar")
      5 tx1.commit()
      6 put("/a/b", "foo", "qux")
      7 tx2.commit()
      
      8 assertEquals("bar", get("/a/b", "foo"))
      


      Thanks,
      --
      dave


        • 1. Re: Transactional behavior when creating new nodes
          belaban

          REPEATABLE_READ extends to the scope of the TX. Inside TX1, once you have read /a/b, you are guaranteed that the value remains the same until you commit or roll back TX1. (We use R/W locks do implement this). So when TX1 commits in line 5, TX2 will be able to acquire the WL (upgrade from a RL) in line 6, on which it was blocked before TX1 committed because TX1 had the WL (and WLs are exclusive).
          So the assert() on line 8 *must* show the value that TX2 modified if TX2's put() came before the assert().

          • 2. Re: Transactional behavior when creating new nodes
            dpinkney

            Thanks for the reply Bela.

            My confusion is related to the case where the node doesn't exist. I have since concluded that since there is no node, there is nothing to lock, and so the best approach is to always make sure the node exists before trying to examine it.

            In my testing, if I were to change line 6 to be a get() instead of a put(), tx2 would see the value committed by tx1 (for tx2, the gets on line 3 and 6 produce different results) - doesn't that violate the REPEATABLE_READ semantics? Would it be safe to say that the locking semantics within a transaction only apply if the node exist at the start of the transaction?

            Thanks,
            --
            dave

            • 3. Re: Transactional behavior when creating new nodes
              belaban

              No, if you change line 6 to a get(), then we do see the change made by TX, but that's similar semantically to phantom reads, which are not prevented by REPEATABLE_READ. If you want to prevent phantom reads, use SERIALIZABLE