在不冲突的情况下使用行锁时防止死锁

时间:2019-07-10 19:59:34

标签: sql sql-server sql-server-2017

我有一个简单的表Item,其中有十几列,主键是2列,ItemId nvarchar(20)Tag nvarchar(200)

我们已经将所有select语句切换为使用WITH (NOLOCK)只是为了确保如下所示:

SELECT ItemId, Tag, Description FROM Item WITH (NOLOCK) WHERE Tag LIKE 'PART_00%'

现在我有主服务器要接收一份工作,他必须删除并重新创建他收到的每个项目。该服务器选择要执行的所有操作的列表(无重复项),然后将此列表分为多个部分,并将每个子列表发送给其他服务器。这些其他服务器做简单的事情:

  1. 从数据库中删除零件
  2. 对文件和类似内容进行一些处理
  3. 在数据库中创建新记录

现在,实际问题是由于资源的限制,我PageLock由于SQL正在将RowLock升级为PageLock而出现了死锁。我们实际上并不在乎,因此我禁用了表锁升级,并更改了删除查询以确保我们使用的是RowLock,所以这就是查询

DELETE FROM Item WITH (ROWLOCK) WHERE Tag LIKE 'PART_0010C'

现在,即使我们已尽一切努力使用KeyLock,我们仍在此表的主键上获得RowLock。基于System_health:event_file,我确实遇到了2个完全不同的pk值的冲突。这怎么可能呢 ?查询也不在事务中,以确保没有任何形式的圆形锁。

在下面,您可以清楚地看到2个完全独立的连接,即pId 109和111(仅执行上面显示的delete语句)正在创建KeyLock,即使实际查询是针对2个不同的特定pk值。

enter image description here 为此,尝试了不同的查询,现在我使用LIKE而不是使用=进行删除。我之所以需要使用LIKE的原因是在工作时间以外运行的其他一些流程将使用LIKE删除,因为许多记录需要删除,并且它们以特定的Tag开头,所以批量删除要快得多。无论如何,使用=都无法解决问题。我还有很多KeyLock

0 个答案:

没有答案