I believe I've found a deadlock problem caused by the way the MsSql dialects apply locking hints that achieves a different behavior than, say, Oracle.
The Oracle dialect generates SQL like "SELECT ... FROM tblBase INNER JOIN tblSubclass ... FOR UPDATE". The "FOR UPDATE" locks all tables: tblBase and tblSubclass.
The MsSql dialect generates SQL like "SELECT ... FROM tblBase WITH (updlock,rowlock) INNER JOIN tblSubclass ...". The "WITH (updlock,rowlock)" is a locking hint for tblBase only! The tblSubclass gets no lock (actually, a default "select" lock). This leads to deadlocks when concurrent threads are both in the midst of trying to update an entity fetched with Upgrade lock.
The nature of the deadlock is as follows (see attached Deadlock.png) with a base class (Order) and subclass (CustomerOrder) and two transactions (85 and 89):
1. [85] SELECT ... FROM tblOrders WITH (updlock,rowlock) INNER JOIN tblCustomerOrders ... This gives [85] an "S" on tblCustomerOrders and an "U" on tblOrders 2. [85] UPDATE tblOrders SET Version=3 ... This upgrade's [85]'s "U" lock on tblOrders to an "X" lock 3a. [89] SELECT ... FROM tblOrders WITH (updlock,rowlock) INNER JOIN tblCustomerOrders ... This statement starts by obtaining an "S" lock on tblCustomerOrders, but then... it's blocked trying to get a "U" lock on tblOrders (because of statement #1 above) Meanwhile... 3b. [85] UPDATE tblCustomerOrders ... This requires [85] to request an "X" lock on tblCustomerOrders where it previously only had a "S" lock. But it can't because statement #3 has an "S" lock on it.
Note that a deadlock still exists without optimistic version control except, but with a "U" lock on tblOrders from [85] instead of an "X".
While I think Hibernate has the philosophy of locking the base table instead of the subclass table, this leads to very real deadlock situations. While locking the subclass tables *instead of* the base class tables would be a mistake, I believe locking the base table *and* subclass table would prevent the deadlocks already prevented by the base-class-only locking philosophy as well as the deadlocks described in this issue.
So how off am I here?
|