I'm getting frequent deadlocks on SqlServer 2008. Currently, I have the following code in my data access layer to deal with it. It basically catches the deadlock and tries to resubmit the command with a new connection. No transactions. But it doesn't seem to work - users still get exceptions and my log shows that most of those exceptions were deadlocks. Can anyone tell what am I doing wrong? Thanks.
private static SqlDataReader ExecDataReader(SqlCommand comm, CommandBehavior behavior)
{
try { return comm.ExecuteReader(behavior); }
catch(SqlException ex)
{
if(ex.Number == 1205 && comm != null)
{
// Deadlock. Can't resubmit with the same connection,
// have to recreate it.
SqlParameterCollection pars = comm.Parameters;
string str = comm.Connection.ConnectionString;
string sproc = comm.CommandText;
int t = comm.CommandTimeout;
try
{
comm.Cancel();
if(comm.Connection != null &&
comm.Connection.State != ConnectionState.Closed)
comm.Connection.Close();
}
catch { }
// Trying to execute it after a random number of seconds
// in order not to get a deadlock again by executing both
// deadlocked commands at the same time. The GetRamdom
// method works as expected, returns totally random number
// in expected range
Thread.Sleep(GetRandom());
SqlConnection conn2 = new SqlConnection(str);
conn2.Open();
SqlCommand comm2 = conn2.CreateCommand();
comm2.CommandText = sproc;
comm2.CommandType = CommandType.StoredProcedure;
comm2.CommandTimeout = t;
CopyParameters(pars, comm2);
return ExecDataReader(comm2, behavior);
}
else throw;
}
}
It is not common for a read to cause a deadlock but it can happen
It will only happen if it conflicts with an update transaction
Look at all the read and updates
I know I am going to get lambasted for this but try the reader command with (no lock)
You can get dirty reads but then your reads will not cause nor be the victim of a deadlock
If that works you can try rowlock
Maybe post the locks and update command(s)
What you want is consistent order of updates
Try and break up the updates
If you really need to update a lot of rows some times you are better off taking a tablock
Another thing to look at is for the Readers you have get in and get out
Don't do processing in the Reader.Read and hold the connection open
Close the reader and connection as soon as you are done