Best way to deal with deadlock in SqlServer?

804 views Asked by At

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;
        }
    }
2

There are 2 answers

1
paparazzo On BEST ANSWER

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

2
AudioBubble On

Your C# looks fine. But sometimes deadlocks are just unavoidable for various reasons. You need to detect the statement/sproc where deadlocks still happen and use the sp_getapplock to lock that code on the server level.