views:

328

answers:

1

I have a problem where I get a deadlock on a MS SQL Server. The same code runs without problems on MySQL.

My problem is that I receive a request to delete a job (which is attached to a device), and afterwards I receive a request to create a new job for the same device. Most times this works without any problems, but once in a while the delete request is not finished when I receive the request to create a new job for the device, and this is where I get the deadlock.

The application is running on JBoss, and I receive the requests from a message queue.

I have found out that I probably could solve the problem on MSSQL using the rowlock keyword, but how do I enable this when using named queries and at the same time supporting MySQL?

Or are there any other way I could ensure that one request finishes before running the next request for the same device?

A stacktrace with some parts removed looks like the following:

2009-08-11 10:03:22,621 WARN  [org.hibernate.util.JDBCExceptionReporter] SQL Error: 1205, SQLState: 40001
2009-08-11 10:03:22,621 ERROR [org.hibernate.util.JDBCExceptionReporter] Transaction (Process ID 200) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
2009-08-11 10:03:22,621 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.exception.LockAcquisitionException: could not delete: [dme.dm.device.Task#131]
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:82)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
---cut cut cut---
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Transaction (Process ID 200) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source)
---cut cut cut---
A: 

From a collegue I heard that he for a long time has tried to make MSSQL use rowlock instead of pagelock, but with no luck. Every time he has had to make a work around, like catching the exception and rerunning the query.

In my case I am using EJB's so I could not even see how to enforce rowlocks with hibernate.

That it is a pagelock that is the problem, is the only explanation I can find. There is no connection between what is deleted and what is inserted, except the device (which is untouched) and the tables used.

So the solution for now is to catch the exception, and rerun the deletion.

homaxto