假设我使用C#运行长时间运行的SQL Server存储过程(比如说30分钟)。进一步假设我在C#中的查询上设置了1个小时的超时时间,这样,如果由于某种原因此SP花费的时间比预期的长,我就不会垄断数据库。最后,假设此存储过程中有一个try / catch块来捕获错误,并在其中的任何步骤失败时进行一些清理。
一些代码(C#):
using (SqlCommand comm = new SqlCommand("longrunningstoredproc")) { comm.Connection = conn; comm.CommandType = CommandType.StoredProcedure; comm.CommandTimeout = 3600; comm.ExecuteNonQuery(); } /* Note: no transaction is used here, the transactions are inside the stored proc itself. */
T-SQL(基本上相当于以下内容):
BEGIN TRY -- initiailize by inserting some rows into a working table somewhere BEGIN TRANS -- do long running work COMMIT TRANS BEGIN TRANS -- do long running work COMMIT TRANS BEGIN TRANS -- do long running work COMMIT TRANS BEGIN TRANS -- do long running work COMMIT TRANS BEGIN TRANS -- do long running work COMMIT TRANS -- etc. -- remove the rows from the working table (and set another data point to success) END TRY BEGIN CATCH -- remove the rows from the working table (but don't set the other data point to success) END CATCH
我的问题是,当命令从C#端超时时,SQL Server将如何处理查询?它会调用SP的catch块,还是只是将其完全切断以便我需要用C#代码执行清理?
超时由ADO.NET强制执行。SQL Server不知道诸如命令超时之类的事情。.NET客户端将发送“注意” TDS命令。您可以使用SQL事件探查器观察此行为,因为它具有“注意”事件。
当SQL Server收到取消消息时,它将取消当前正在运行的查询(就像按停止按钮时SSMS所做的一样)。它将中止批处理(就像在SSMS中一样)。这意味着无法运行捕获代码。连接将保持活动状态。
以我的经验,该交易将立即回滚。我不认为这是可以保证的。
TL; DR:ADO.NET中的超时行为与您在SSMS(或称为SqlCommand.Cancel)中按Stop的行为相同。
SqlCommand.Cancel
这是对此的参考:https : //techcommunity.microsoft.com/t5/sql-server-support/how-it-works-attention- attention-or-should-i-say-cancel-the/ba-p/ 315511