struggling on concurrent transaction issues


EJB design: struggling on concurrent transaction issues

  1. struggling on concurrent transaction issues (2 messages)

    Scenery for a transaction time-out problem: (For simplicity, I just describe the "happy scenery" without any try-catch block)

    1. We use stateless session bean (say, Manager) to handle entity bean (say, NE).

    2. We use BMT(Bean managed transaction) at stateless session bean(say, Manager) level and the Transaction-Type for Entity Bean (say, NE) is "Supports".

    3. Suppose two functions inside the Manager:

    void updateNE(int neNum, String ne_name)
      UserTransaction trans = .... // get user transaction
      NE ne = NEHome.findByPrimaryKey(new Integer(neNum));

    void removeNE(int neNum)
      UserTransaction trans = ... // get user transaction
      NE ne = NEHome.findByPrimaryKey(new Integer(neNum));
      // remove some other table records...
      // do something
      ne.remove(); // remove the NE record

    If one client try to remove a NE and another client try to update the SAME NE at the SAME TIME (we simulated this situation), very likely there is a time-out exception and the trace file shows that the two transactions are waiting for the other to release the lock on NE and hangs right before Transaction.commit().

    My questions is:
    1. does Transaction guarantee that the shared resource (here is NE) will not block each other and the second one waits the first one to finish?
    2. what does it happen when NEHome.findByPrimaryKey() INSIDE a transaction?

    I've been struggling on this problem for a couple of days and tried various way to solve this problem, like changing the isolation level to TRANSACTION_SERIALIZABLE, and NOT succeeds.

    I really confuse where is the rate condition/dead lock happens here in this simple scenery!

    It would be greatly appreciated if anyone can provide some option or suggesstions on this.


    Long Tang
  2. The deadlock is caused by the upgrade of a "read" lock to a "write" lock. Both clients start with a read lock, and then at commit time there is an attempt by both clients to upgrade this to a write lock. Both clients will wait forever (or until timeout).

    To solve this, change the "findByPrimaryKey" to "findByPrimaryKeyForUpdate". This will be specific to the app server product you are using. Some app servers allow you to declare that all findByPrimaryKey calls should be "for update". Otherwise you have to write a custom finder that includes the "FOR UPDATE" clause (assuming you are mapping to a relational database). Check your app server's documentation for how to write a custom finder.

    When you make this change, the first client to execute "findByPrimaryKeyForUpdate" will get an exclusive lock on the entity, and all others will wait in line.
  3. thank you for this. i checked the WL docs and changed the locking mechanism to Exclusive for all the entity beans and it seems works.