3 Replies Latest reply on Nov 30, 2005 3:46 PM by steview

    Read committed isolation is partially incorrect

    steview

      The READ COMMITTED level is partially incorrect depending on what order read and write locks are acquired by the transactions. The following code allows uncommitted values to be seen (it is part of a junit test).

      TreeCache cache =new TreeCache();
      cache.setCacheMode(TreeCache.LOCAL);
      cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
      cache.setIsolationLevel(IsolationLevel.READ_COMMITTED);
      cache.createService();
      cache.startService();

      TransactionManager mgr = cache.getTransactionManager();

      //transaction 1
      mgr.begin();
      cache.put(Fqn.fromString("test"),"testKey","test");
      mgr.commit();

      // transaction 2
      mgr.begin();
      cache.get(Fqn.fromString("test"),"testKey");
      Transaction tx = mgr.getTransaction();
      mgr.suspend();

      // transaction 3
      mgr.begin();
      cache.put(Fqn.fromString("test"),"testKey2","test");
      Object obj =cache.get(Fqn.fromString("test"),"testKey");
      Object obj2 =cache.get(Fqn.fromString("test"),"testKey2");
      assertNotNull(obj);
      assertNotNull(obj2);
      Transaction tx2 = mgr.getTransaction();
      mgr.suspend();

      // transaction 2
      mgr.resume(tx);
      Object obj3 =cache.get(Fqn.fromString("test"),"testKey");
      Object obj4 =cache.get(Fqn.fromString("test"),"testKey2");
      assertNotNull(obj3);
      System.out.println(obj3);
      assertNull(obj4);
      mgr.commit();
      mgr.resume(tx2);
      mgr.commit();


      The second block of transaction 2 can see the data that has been put into the node by tx1 even though tx1 has not committed yet. (The assertNull(obj4) fails).


      However, if I do this:

      //transaction 1
      mgr.begin();
      cache.put(Fqn.fromString("test"),"testKey","test");
      mgr.commit();

      // transaction 2
      mgr.begin();
      cache.put(Fqn.fromString("test"),"testKey2","test");
      Transaction tx = mgr.getTransaction();
      mgr.suspend();

      // transaction 3
      mgr.begin();
      // cache.put(Fqn.fromString("test"),"testKey2","test");
      Object obj =cache.get(Fqn.fromString("test"),"testKey");
      Object obj2 =cache.get(Fqn.fromString("test"),"testKey2");
      assertNotNull(obj);
      assertNotNull(obj2);
      Transaction tx2 = mgr.getTransaction();
      mgr.suspend();

      The get in transaction 3 for the testKey2 uncommitted value behaves as expected by throwing an exception as it cannot acquire a readlock on the node.

      It appears that if I acquire a readlock first for TxA then a writelock for TxB I can ignore the isolation level and it effectively becomes NONE.