sql-server - 解决 SQL Server 死锁情况

标签 sql-server deadlock

我正在尝试找到一种解决方案来解决 SQL Server 中反复出现的死锁情况。我对探查器跟踪生成的死锁图做了一些分析,并得出了以下信息:

第一个进程(spid 58)正在运行此查询:

UPDATE cds.dbo.task_core
    SET nstate = 1 
    WHERE nmboxid = 89 AND ndrawerid = 1 
        AND nobjectid IN (SELECT
                              nobjectid 
                              FROM (SELECT
                                        nobjectid, count(nobjectid) AS counting
                                        FROM cds.dbo.task_core
                                        GROUP BY nobjectid
                                   ) task_groups
                              WHERE task_groups.counting > 1
                         )          

第二个进程(spid 86)正在运行此查询:

INSERT INTO task_core (…) VALUES (…)

spid 58 正在等待 CDS.dbo.task_core 上的共享页面锁定 (spid 86 持有冲突的意图独占 (IX) 锁)

spid 86 正在等待 CDS.dbo.task_core 上的意图独占 (IX) 页锁定 (spid 58 持有冲突的更新锁)

最佳答案

很高兴您发布了声明和资源。为了充分理解这个问题,这些计划也很有用。但我将进行(有根据的)猜测并诊断死锁原因,因为更新的子查询中发生了大型扫描:

SELECT nobjectid 
    FROM (SELECT nobjectid, count(nobjectid) AS counting
          FROM cds.dbo.task_core
           GROUP BY nobjectid
    ) task_groups
    WHERE task_groups.counting > 1

此查询必须扫描整个task_core 表。总是。您会在页面上遇到死锁,因为全表扫描已优化为使用页面锁定,但如果添加 ROWLOCK 提示,您也可以在行级别遇到死锁。

要消除死锁,必须消除更新过程中发生的全表扫描冲突。您可以尝试使用行级版本控制,在数据库中启用读已提交快照隔离,而不是使用脏读,请参阅 Understanding Row Versioning-Based Isolation Levels .

但是更好的解决方案是首先不进行扫描。首先,重新审视业务逻辑需求和数据模型。每当您看到需要查看整个表才能做出决定的更新时,这是一段非常非常难闻的代码。如果您确实发现更新无法以更明智的方式重写(我怀疑),那么您应该考虑使用索引 View 。 BIG_COUNT(*) 表达式在索引 View 中是允许的,它们会 speed up the query significantly ,除了消除死锁原因之外。

关于sql-server - 解决 SQL Server 死锁情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2449293/

相关文章:

sql-server - 如何插入默认值作为 SQL Server View 定义的一部分?

sql-server - SQL Server 2k5 内存消耗?

php - 拉维 SQL Server : SQLSTATE[HY000]: [unixODBC][Microsoft][ODBC Driver 13 for SQL Server]Protocol error in TDS stream

c# - 从 SQL Server 的事务日志中删除信息

sql-server - 该查询如何在执行计划中生成两个连接运算符?

mysql - 如何避免 MariaDB/Galera 上的队列表出现死锁?

c++ - 带有重复参数的 Scoped_lock

objective-c - 调用dispatch_sync()时发生死锁,即使它在另一个队列上

boost - 加入线程 : "resource deadlock avoided"

mysql - C3p0 - MSSQL 上的表观死锁,但不是 PostgreSQL 或 MySQL