调试严格的LINQ-to-SQL超时

Cra*_*ker 5 linq sql-server deadlock sql-server-2005 linq-to-sql

我在尝试执行LINQ(-to-SQL)查询时遇到超时错误

System.Data.SqlClient.SqlException:超时已过期.操作完成之前经过的超时时间或服务器没有响应.

现在,这是不是只是一个缓慢的查询的情况:

  • 我在SQL Management Studio中运行等效的SQL并快速完成(2秒)
  • 我将我的CommandTimeout设置为2分钟.
  • 当我在单元测试中执行完全相同的查询时,它会成功且快速地完成.那就是:当我在运行此查询以及其他查询时,我只会获得此超时.超时始终发生在同一个呼叫中.

最后一项让我觉得我遇到了某种类型的数据库端死锁:查询被某个地方的锁阻塞,超时时间过去,导致停止连接.

这个想法的问题在于我在DataContext中做选择导致问题.(我确实在不同的数据库/ DataContexts中发生了插入.)我也没有显式事务.这让我有点沮丧:查询行为看起来就像死锁一样,但我从未遇到过以前由某种事务隔离问题引起的死锁 - 这看起来不像这里的情况(乍一看).

我正在寻找有关如何调试此问题的建议.我应该考虑什么样的事情来确定这个问题的原因?

编辑

一些可能有用的注释:

  • 我正在查询引用的视图:
    • 同一数据库中的其他视图
    • 通过链接服务器指向另一个数据库中的表的同义词.
  • 此视图union用于将多个查询的结果连接在一起

结语

我最终通过重新处理查询来修复核心问题.原来不止一次地调用几张桌子(通过不同的视图).重新设计的版本绕过了所有这些,超时消失了.

KM.*_*KM. 4

再次从应用程序运行您的代码,同时等待(2 分钟??)在查询窗口中运行以下代码:

;with Blockers AS
(SELECT
     r.session_id AS spid
         ,r.cpu_time,r.reads,r.writes,r.logical_reads 
         ,r.blocking_session_id AS BlockingSPID
         ,LEFT(OBJECT_NAME(st.objectid, st.dbid),50) AS ShortObjectName
         ,LEFT(DB_NAME(r.database_id),50) AS DatabaseName
         ,s.program_name
         ,s.login_name
         ,OBJECT_NAME(st.objectid, st.dbid) AS ObjectName
         ,SUBSTRING(st.text, (r.statement_start_offset/2)+1,( (CASE r.statement_end_offset
                                                                   WHEN -1 THEN DATALENGTH(st.text)
                                                                   ELSE r.statement_end_offset
                                                               END - r.statement_start_offset
                                                              )/2
                                                            ) + 1
                   ) AS SQLText
     FROM sys.dm_exec_requests                          r
         JOIN sys.dm_exec_sessions                      s ON r.session_id = s.session_id
         CROSS APPLY sys.dm_exec_sql_text (sql_handle) st
     --WHERE r.session_id > 50
)
SELECT Blockers.* FROM Blockers
Run Code Online (Sandbox Code Playgroud)

它会显示运行时的所有块。