asp.net - .net SqlCommandTimeOut 和连接池

标签 asp.net .net sql-server

假设我们正在执行许多不同的 sql 命令,并且 SqlCommand.CommandTimeout 保留默认值 30 秒。

我们假设其中一些 sql 命令只是长查询,我们可能会遇到超时异常。

如果我错了,请纠正我,这个异常只是导致.Net不想再等待,但是如果我们使用连接池,这个连接可能会保持打开状态,所以该sql语句可能仍然在SQL 服务器端?或者这些系统之间存在一些隐藏的通信,无论我们是否使用连接池,它都会突然停止?

只是想知道其机制是什么以及它是否会影响SQL Server的性能。我的意思是,如果查询真的很长,例如需要 10 分钟才能运行(如果它仍在运行),则可能会不必要地减慢服务器速度,因为没有人可以获得结果。

更新

所以在这里我特别询问连接池,代码肯定会通过异常处理关闭连接,或者我们可以假设正在使用由 @dash 在这里命名的首选模式的代码。问题是,如果我在该 SqlConnection 对象上调用 Close() 或 Dispose() 方法,它将返回到连接池,而不是物理上关闭它。

我问当它返回到池中时,那个长查询是否仍在 SQL Server 端运行。如果可能的话,如何避免这种情况。

再次更新

感谢 @dash 提到关于数据库事务,是的,回滚会让它等待,我们还没有关闭连接并将其返回到池中。那么,如果它只是一个长选择查询或一个更新,但只是一个单独的更新而不涉及任何数据库事务呢?具体来说,我想知道是否有一种方法可以告诉 SQL Server 我现在不需要结果,请停止运行它?

最佳答案

这完全取决于您实际执行查询的方式;

想象一下以下查询:

SqlConnection myConnection = new SqlConnection("connection_string");

SqlCommand myCommand = new SqlCommand();
myCommand.Connection = myConnection;
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandTimeout = some_long_time;
myCommand.CommandText = "database_killing_procedure_lol";

myConnection.Open() //Connection's now open

myCommand.ExecuteNonQuery();

有两件事会发生;一是此方法将排队直到 command.ExecuteNonQuery() 完成。第二个是,我们还将在该方法的持续时间内从连接池中绑定(bind)一个连接。

如果超时会发生什么?好吧,抛出了一个异常 - 带有 Number 属性 = -2 的 SqlException。但是,请记住,在上面的代码中,没有异常管理,因此所发生的只是对象超出范围,我们需要等待它们被处理。特别是,在这种情况发生之前,我们的连接将无法重用。

这是首选以下模式的原因之一:

using(SqlConnection myConnection = new SqlConnection("connection_string"))
{
    using(SqlCommand myCommand = new SqlCommand())
    {

        SqlCommand myCommand = new SqlCommand();
        myCommand.Connection = myConnection;
        myCommand.CommandType = CommandType.StoredProcedure;
        myCommand.CommandTimeout = some_long_time;
        myCommand.CommandText = "database_killing_procedure_lol";

        myConnection.Open() //Connection's now open

        myCommand.ExecuteNonQuery();    

    }

}

这意味着,一旦查询完成,无论是自然完成(运行至完成)还是通过异常(超时或其他方式),资源都会立即归还

在您的具体问题中,由于多种原因,需要很长时间才能执行的大量查询是不好的。在 Web 应用程序中,可能有许多用户争夺有限数量的资源;内存、数据库连接、CPU 时间等。因此,将其中任何一个与昂贵的操作捆绑在一起都会降低 Web 应用程序的响应能力和性能,或限制您可以同时服务的用户数量。此外,如果数据库操作成本高昂,您也可能会占用数据库,从而进一步限制性能。

仅出于这个原因,尝试降低数据库查询的执行时间总是值得的。如果不能,那么您必须注意可以同时运行多少个此类查询。

编辑:

所以您实际上对 SQL Server 端发生的事情感兴趣...答案是...这取决于! CommandTimeout 实际上是一个客户端事件 - 你的意思是,如果查询花费的时间超过 n 秒,那么我不想再等待了。 SQL Server 被告知情况确实如此,但它仍然需要处理当前正在执行的操作,因此 SQL Server 实际上可能需要一些时间才能完成查询。它会尝试优先考虑这一点,但仅此而已。

对于交易尤其如此;如果您正在运行包含在事务中的查询,并且将其作为异常管理的一部分回滚,那么您必须等到回滚完成。

人们 panic 并开始发出 KILL 的情况也很常见。针对运行查询的 SQL 进程 ID 的命令。如果命令正在运行事务,这通常是一个错误,但对于长时间运行的选择来说通常没问题。

SQL Server 必须管理其状态以保持一致。客户端不再监听的事实意味着您浪费了工作,但 SQL Server 仍然需要自行清理。

所以,是的,ASP.Net 方面的事情会很好,因为它并不关心,但 SQL Server 仍然必须完成它开始的工作,或者达到可以安全放弃该工作的程度,或者回滚已开立的任何交易的任何变化。

这显然可能会对数据库服务器的性能产生影响,具体取决于查询!

即使在事务之外长时间运行的 SELECT 或 UPDATE 或 INSERT 也必须完成。 SQL Server 将尝试尽快放弃它,但前提是这样做是安全的。显然,尤其是对于更新和插入,它必须达到数据库仍然一致的程度。对于 SELECT,它将尝试尽快结束。

关于asp.net - .net SqlCommandTimeOut 和连接池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9782198/

相关文章:

sql - 为什么我的 126 日期时间没有返回中间有 T 的内容?

sql-server - 以编程方式将数据库用户设置为 db_owner

sql - 从长度中选择最大值

c# - 将日期插入文本框,然后在日历 asp.net c# 中选择该日期

C#:XML 转换

.net - 如何在 vb.net 中刷新 Datagridview

c# - 委托(delegate)方法的简洁事务

asp.net - 欺骗 IsPostBack

c# - 为什么 mvcaction4 代码片段没有反应?

c# - 尝试在 ASP.NET 页面上显示 Crystal 报表时出错