处理事务(进程ID X)已死锁

时间:2019-05-31 01:02:40

标签: c# sql .net sql-server ado.net

我在SQL Server 2016-ADO.NET连接上的查询中收到以下错误消息

异常消息:事务(进程ID 358)在锁定时死锁|与另一个进程通信缓冲资源,并已被选为死锁受害者。重新运行事务。

SELECT * FROM Table2 WHERE EXISTS ( 
                       SELECT * FROM Table1 
                      WHERE Id = '1234' 
                      AND SourceId = Table1.[Id]);

什么可能导致此问题?

运行此查询时创建的共享/读取锁的作用域是什么?即,共享锁是应用于整个Table2还是仅应用于结果集中的行? (我问这是因为它看起来像一个相关的子查询)

将其重构为INNER JOIN会有所帮助吗?

SELECT t2.* FROM Table2 t2
INNER JOIN  Table1 t1
ON t2.SourceId = b.Id
WHERE t1.Id = '1234' 

从日志中我看不到任何其他更新语句,它们在发生错误时会在+/- 10秒内更新结果集(或表)。

那么运行同一查询的多个用户会产生死锁吗? (表上没有非聚集索引)

使用索引策略帮助解决死锁情况会加快查询速度吗? 该表有200万条记录,并且没有正确索引(它只有一个主键(不是SourceId))。我在执行计划中看到索引扫描。因此,在SourceId上添加覆盖其他列的非聚集索引有帮助吗? 我看到这将需要额外的400 MB空间用于索引数据结构。因此,我绝对不希望这样做。 是否会在SourceId上添加非聚集索引(不包括索引)有帮助?(由于空间限制)

我们的应用程序的默认隔离级别为“重复读取”。使用WITH(NOLOCK)放宽隔离级别会有所帮助吗?

我怎么知道与此冲突的另一个SQL语句呢?是否可以在生产数据库中运行SQL事件探查器以生成DeadLock图?

建议使用其他什么方法来识别和解决此问题?

1 个答案:

答案 0 :(得分:0)

降低隔离级别并不能帮助锁定用户..但可以帮助其他使用锁定表的用户..将隔离级别降低为“读取未提交”对每个表中的No Lock语句都具有相同的作用。