SQL Server:死锁受害者。重新运行该交易

时间:2016-08-08 17:21:00

标签: sql-server

我知道这个错误已被涵盖,这是关于我真正追求的更广泛的图片的更多建议。

我的帐户仅限于在第三方应用程序拥有的数据库中的少数几个表上进行SELECT。这个想法是我们可以安全地在这里和那里查询奇怪的东西,而不必请求第三方为我们做出改变(他们没有很好的响应)。

这表面上已经工作正常,直到今天早些时候我注意到日志中有异常(参见帖子标题)。

鉴于该查询是:

SELECT 
    DATEDIFF(ss, '01-01-1970 00:00:00', (SELECT MAX(CREATEDDATE) 
                                         FROM VISITS 
                                         WHERE CUSTID = 31))

并且DBCC USEROPTIONS告诉我隔离级别是读取提交的,为什么上述内容会与任何内容发生冲突?我可以理解它得到一个过时的值,但为什么只在一个承诺的读取上冲突?

无论如何,让我更担心的是另一端可能发生的事情。如果第三方应用程序遇到类似错误并且没有人注意到(他们不会匆忙)该怎么办?

任何人都可以把我的想法放在另一端(同样,我只是做SELECT s),并且可能还建议在这种情况下的最佳实践? SQL并发性不是过去我不得不过分担心的事情。

由于

1 个答案:

答案 0 :(得分:0)

这种死锁通常与表中值和受影响索引的访问路径有关。上面的查询包含一个聚合(最大),所以至少(没有双关语)它必须查找所请求客户的行中的最大值。可能有一个支持它的索引。但是,在搜索过程中,即使是简短的,也需要锁定数据以防止更新。同时,更新查询可能会使用不同的索引序列来访问数据,并且需要使用独占锁来允许更新。所以,是的,读取已提交的隔离,只是正确的更新,并选择可以死锁。

最佳长期解决方案可能是RCSI(读取提交快照隔离),它允许读取使用“旧”版本的行而不是表中修改的实时/热值。但是,如果您有第三方应用程序,那么供应商必须先测试并支持该设置,然后才能打开它。不要只是打开它。这是一个很棒的功能,但需要针对特定​​应用进行测试。也就是说,通常需要的更改很少或没有,但有一些例外。

如果不这样做,仔细研究服务器上这样的真实事件的死锁图可能会产生一种改变索引的方法,可能会阻止死锁。

最后,您可以改为读取未提交的数据,但结果是它可能始终不是100%准确。