This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
Hello, I believe that my program is suffering from some sort of deadlock, and I was hoping for some feedback. I am helping to develop a trading system using EJBs, Oracle 9i, and Bea Weblogic 7.0. The system provides an entity EJB called LiveOrder that exposes several finder methods, most of which return java.util.Collections of LiveOrder EJBs. In weblogic-ejb-jar.xml, I have set the transaction isolation-levels for these finders to TRANSACTION_READ_COMMITTED_FOR_UPDATE (b/c TRANSACTION_SERIALIZABLE isn't really supported by Oracle), in an effort to eliminate phantom reads, which occur frequently if I do not use this isolation level. These finders all use transaction attribute 'Required'. It is my understanding that any transaction that calls any of these finders either will lock the database if no other transaction already owns the lock, or will wait until the lock is released if another transaction owns that lock. It also is my understanding that a transaction that owns a lock will always release any locks acquired upon expiration of that transaction (whether that be via commit or via rollback). However, this doesn't always appear the case: I have noticed occassionally that several clients "hang," as they wait for the lock that, for some reason, is not being released by its transaction. There do not appear to be any exceptions thrown by the system prior to the system hanging, and the Weblogic administration tool states that all transactions have been committed. If it helps, I have included the general algorithm for the main (i.e., most expensive) transaction: 1. a client calls a stateless session EJB's processOrder method (which should implicitly start a new transaction, b/c this method has attibute 'RequiresNew') 2. the transaction invokes the LiveOrder finder method (this should lock the DB, so subsequent callers should block until the lock is released). 3. the transaction invokes another LiveOrder finder method, returning a separate set of data. 4. the transaction invokes a finder method from a separate entity EJB (called Security), which maps to a "read-only" table in the DB (default transaction-isolation level, Required attribute). 5. the transaction invokes a finder method from yet another separate entity EJB (called SecurityMarketValues), which maps to some other table (not read-only) in the DB (again, default transaction-isolation level, Required attribute). 6. the transaction writes to the SecurityMarketValues entity EJB. 7. the transaction writes to the LiveOrders retrieved from steps 2 and 3. 8. the transaction ends by exiting method processOrder (thus releasing the locks on the LiveOrder table in the DB).
In the system, there also exist other transactions that occassionally call the LiveOrder EJB finder methods, but only briefly to take a "snapshot" of the live order table (i.e., these transactions do not make calls to other DB tables, and close transactions almost immediately after starting them) Like I mentioned before, the system sometimes works, and sometimes it hangs. Any ideas? I'm running out... Thanks, Jon
If there was an Oracle deadlock the DB would resolve it momentarily and will ultimately choose one transaction and throw an exception so it's not a DB deadlock. Take a thread dump at the very moment your system seems to be hanging and look at what the threads are doing. From your description it's not very unlikely that those threads of yours that take snapshots of the data will not disrupt the transactions so you may be surprised by the thread dumps that this is actually what happens -- those snapshot thread wait for some lock while holding locks needed by you other threads and it just slows down the system.
Thanks Jim, I took your advice, examined the code, and found several (very useless) calls to a sequence in Oracle 9i that generates primary keys. I eliminated these calls, as well as moved some additional database calls outside of the transaction that locked the database (ensuring that the transaction is as fast as possible; the transaction doesn't hold on to the lock too long). Thanks again, Jon
Joined: Jan 05, 2001
Great to hear! Mark H. has always been helpful so it's nice he can get help in return. From the BEA side, if you think you have a problem those BEA newsgroups at newgroups.bea.com have always been a lifesaver for me.