【问题标题】:DELETE command times outDELETE 命令超时
【发布时间】:2014-08-13 20:43:09
【问题描述】:

我有一个DELETE 命令,当我从我的应用程序运行它时会超时。为了进行调查,我在 SQL Server Management Studio 中放置了相同的命令并立即执行。谁能指出我正确的方向以找到延迟的原因?

在 SQL Server Management Studio 中,我输入了:

DECLARE @docid INT;
SET @docid = 41;
DELETE FROM reports WHERE doc_id=@docid;

reports 表只有 5 行,其中 1 行的 docid 为 41。

报告表非常简单:

CREATE TABLE [dbo].[reports](
    [doc_id] [int] NULL,
    [candidate_id] [int] NULL,
    [report] [varbinary](max) NOT NULL,
    [ext] [nvarchar](10) NULL

对两个 id 都有一些限制。

更多信息:

  • 如果我从同一个地方的其他表中删除,那会很高兴。
  • 连接到同一台机器上的本地实例。

这是我在应用程序中执行时遇到的异常:

{System.Data.SqlClient.SqlException (0x80131904):超时。 在操作完成之前经过的超时时间或 服务器没有响应。 ---> System.ComponentModel.Win32Exception (0x80004005): 等待操作超时 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常, Boolean breakConnection,Action1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource1 完成,Int32 超时,Task& 任务, 布尔 asyncWrite) 在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 完成,字符串方法名,布尔型 sendToPipe,Int32 超时, 布尔 asyncWrite) 在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()

【问题讨论】:

  • “报告”表上是否有任何触发器或级联关系?
  • 可能是死锁或循环引用?
  • 您的程序中是否有多个连接,而另一个可能从表中读取数据?
  • 尝试SELECT * FROM SYS.SYSPROCESSES 看看是否有任何被阻止(当您的应用正在删除时)?如果是这样,您可以通过执行 DBCC INPUTBUFFER(##) 来获得代码阻塞,其中 ## 是阻塞连接的 SPID。
  • 您使用的是什么版本的 SQL Server 和 SSMS? SSMS 2008 及更高版本,右键单击您的连接并选择“活动监视器”。任何打开的连接以及它们所处的状态都将在此处列出。执行查询时,如果它被阻塞,它将引用另一个连接。

标签: c# sql-server


【解决方案1】:

您可以运行它来查看所有正在运行的查询(和正在运行的代码),以及阻塞 spid 的详细信息...一旦您确定了罪魁祸首,您就可以从那里开始。

您需要在应用超时时运行此程序才能正确获取信息。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
IF OBJECT_ID('TEMPDB..#SPID') IS NOT NULL DROP TABLE #SPID
DECLARE @InputBuffer TABLE (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        SPID INT,
        BLOCKED INT,
        CPU BIGINT,
        PHYSICAL_IO BIGINT,
        EventType [nvarchar](1024),
        Parameter [int],
        EventInfo [nvarchar](MAX)
    )

DECLARE @SPID INT, @ID INT, @CPU BIGINT, @IO BIGINT, @BLOCKED INT

select spid, blocked, SUM(cpu) as cpu, SUM(physical_io) as physical_io
INTO #SPID
from sys.sysprocesses
where  status<>'sleeping'
group by spid, blocked

DECLARE SPID CURSOR LOCAL
FOR 
SELECT SPID, BLOCKED, CPU, PHYSICAL_IO FROM #SPID
OPEN SPID
FETCH NEXT FROM SPID INTO @SPID, @BLOCKED, @CPU, @IO
WHILE @@FETCH_STATUS=0
BEGIN
    INSERT INTO @InputBuffer (EventType, Parameter, EventInfo) EXEC('DBCC INPUTBUFFER('+@SPID +')')
    SET @ID = SCOPE_IDENTITY()
    UPDATE @InputBuffer SET SPID = @SPID, BLOCKED=@BLOCKED, CPU = @CPU, PHYSICAL_IO = @IO WHERE ID = @ID
    FETCH NEXT FROM SPID INTO @SPID, @BLOCKED, @CPU, @IO
END
CLOSE SPID
DEALLOCATE SPID

UPDATE @InputBuffer SET EventInfo = REPLACE(EventInfo,'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED','')
DELETE FROM @InputBuffer WHERE EventInfo='sys.sp_reset_connection;1' or EventInfo is null
SELECT * FROM @InputBuffer ORDER BY PHYSICAL_IO desc

【讨论】:

    【解决方案2】:

    我不太确定,但这可能在表被死锁时发生。检查该表是否特别是死锁。

    【讨论】:

    • 是否有任何聪明的工具或可以帮助做到这一点的东西?我已经通过检查代码尝试了老式的方法......!
    • 我实际上并不熟悉 SQL Server 具体是如何做事的,所以我可能是错的,但这如何解释它针对一个前端而不是另一个前端?他的应用程序失败了,但另一个应用程序与运行相同命令的同一数据库交互却没有。假设他在运行之间重新初始化了数据库,那么行为应该是相同的。我的直觉告诉我,这更多是操作配置问题或客户端上的问题,而不是数据库本身的问题。
    • 在 SQL Server Management Studio 中,右键单击服务器节点并选择“活动监视器”。展开“进程”窗格,并等待它填充(这可能需要几秒钟)。您将能够看到服务器上的每个进程、它正在工作的数据库、它的等待状态以及它被“阻止”的对象。您可以右键单击任何进程并选择“详细信息”以查看它正在执行的内容。
    • 您可以使用 SQLProfiler 并跟踪特定事件。您还可以使用跟踪标志 (msdn.microsoft.com/en-us/library/ms188396(v=sql.110).aspx)。这是另一个有趣的链接:technet.microsoft.com/en-us/library/ms178104(v=sql.105).aspx
    猜你喜欢
    • 2021-09-06
    • 2013-04-03
    • 2013-09-30
    • 2019-12-06
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多