当前位置:  开发笔记 > 编程语言 > 正文

如何在C#中使用ADO获得高效的Sql Server死锁处理?

如何解决《如何在C#中使用ADO获得高效的SqlServer死锁处理?》经验,为你挑选了3个好方法。

我有一个类'数据库',作为ADO.net的包装器.例如,当我需要执行一个过程时,我调用Database.ExecuteProcedure(procedureName,parametersAndItsValues).

我们遇到了SQL Server 2000中死锁情况的严重问题.我们团队的一部分正在处理sql代码和事务以最小化这些事件,但我正在考虑使这个数据库类能够抵御死锁情况.

我们希望死锁受害者可能在经过一段时间的延迟后重试,但我不知道是否可能.这是我们使用的方法的代码:

public int ExecuteQuery(string query)
{
    int rows = 0;

    try
    {
        Command.Connection = Connection;
        Command.CommandType = CommandType.Text;

        if(DatabaseType != enumDatabaseType.ORACLE)
          Command.CommandText = query;
        else
          Command.CommandText ="BEGIN " +  query + " END;";



        if (DatabaseType != enumDatabaseType.SQLCOMPACT)
            Command.CommandTimeout = Connection.ConnectionTimeout;

        if (Connection.State == ConnectionState.Closed)
            Connection.Open();

        rows = Command.ExecuteNonQuery();
    }
    catch (Exception exp)
    {
        //Could I add here any code to handle it?
        throw new Exception(exp.Message);
    }
    finally
    {
        if (Command.Transaction == null)
        {
            Connection.Close();
            _connection.Dispose();
            _connection = null;
            Command.Dispose();
            Command = null;
        }
    }
    return rows;
}

我可以在catch块内进行此处理吗?



1> Sam Saffron..:

首先,我将查看我的SQL 2000代码并深入了解发生此死锁的原因.解决这个问题可能隐藏了一个更大的问题(例如,缺少索引或错误的查询).

其次,我会检查我的架构,以确认经常需要调用死锁语句(select count(*) from bob必须每秒调用100次?).

但是,如果您确实需要一些死锁支持并且在SQL或体系结构中没有错误,请尝试以下几行.(注意:我必须将此技术用于每秒支持数千个查询的系统,并且很少会遇到死锁)

int retryCount = 3;
bool success = false;  
while (retryCount > 0 && !success) 
{
  try
  {
     // your sql here
     success = true; 
  } 
  catch (SqlException exception)
  {
     if (exception.Number != 1205)
     {
       // a sql exception that is not a deadlock 
       throw; 
     }
     // Add delay here if you wish. 
     retryCount--; 
     if (retryCount == 0) throw;
  }
}



2> Neil..:

基于@Sam的响应,我提出了一个通用的重试包装方法:

private static T Retry(Func func)
{
    int count = 3;
    TimeSpan delay = TimeSpan.FromSeconds(5);
    while (true)
    {
        try
        {
            return func();
        }
        catch(SqlException e)
        {
            --count;
            if (count <= 0) throw;

            if (e.Number == 1205)
                _log.Debug("Deadlock, retrying", e);
            else if (e.Number == -2)
                _log.Debug("Timeout, retrying", e);
            else
                throw;

            Thread.Sleep(delay);
        }
    }
}

private static void Retry(Action action)
{
    Retry(() => { action(); return true; });
}

// Example usage
protected static void Execute(string connectionString, string commandString)
{
    _log.DebugFormat("SQL Execute \"{0}\" on {1}", commandString, connectionString);

    Retry(() => {
        using (SqlConnection connection = new SqlConnection(connectionString))
        using (SqlCommand command = new SqlCommand(commandString, connection))
            command.ExecuteNonQuery();
    });
}

protected static T GetValue(string connectionString, string commandString)
{
    _log.DebugFormat("SQL Scalar Query \"{0}\" on {1}", commandString, connectionString);

    return Retry(() => { 
        using (SqlConnection connection = new SqlConnection(connectionString))
        using (SqlCommand command = new SqlCommand(commandString, connection))
        {
            object value = command.ExecuteScalar();
            if (value is DBNull) return default(T);
            return (T) value;
        }
    });
}



3> 小智..:

如果可以在数据层解决死锁,那肯定是要走的路.锁定提示,重新设计模块的工作方式等等.NoLock不是灵丹妙药 - 有时由于事务完整性的原因而无法使用,而且我遇到了直接(尽管很复杂)数据读取的情况,所有相关表NoLock'd仍会导致其他查询出现阻塞.

无论如何 - 如果由于某种原因你无法在数据层解决它,那怎么样

bool OK = false;
Random Rnd = new Random();

while(!OK)
{
    try
    {
        rows = Command.ExecuteNonQuery();
        OK = true;
    }
    catch(Exception exDead)
    {
        if(exDead.Message.ToLower().Contains("deadlock"))
            System.Threading.Thread.Sleep(Rnd.Next(1000, 5000));
        else
            throw exDead;
    }
}


随机计时器upvote,Sams解决方案锤击sql服务器
推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有