1

我们在持有订单履行的事务表中使用集群列存储索引。该表由不同的会话定期更新。但是,每个会话都是专门为了订购作业号而设计的,所以他们并不试图同时更新同一行。但是,由于会议之间的情况不同,我们正面临死锁问题。发生在集群列存储索引中的死锁

  • 行组锁定&页锁
  • 行组锁定&行组锁定

这不是特定于存储的过程。这是由于多个存储过程逐一更新此表,作为订单履行的一部分。

表的示例模式很简单:

CREATE TABLE OrderFulfillments 
(
    OrderJobNumber   INT NOT NULL, 
    FulfilledIndividualID BIGINT NOT NULL, 
    IsIndividualSuppressed BIT NOT NULL, 
    SuppressionReason  VARCHAR(100) NULL 
) 

我已经给定的样本僵局图,供大家参考。请让我知道,我可以采取什么方法来避免这种僵局。我们需要在此表中使用聚集的Columnstore索引,因为我们正在执行聚合操作以查看个人已经实现了多少次。没有列存储索引,它可能会变慢。

enter image description here

+0

你需要问自己什么查询导致了阻塞。如果更新是真正的顺序,那么答案不是更新,而是其他过程,比如说表上的select语句。从sys.DM_exec_requests中找出last_wait_type是什么 –

+0

是的,select语句仍然使用某种级别的锁定。 –

+0

谢谢克利夫顿。我已在每个选择查询上应用NOLOCK。只有UPDATE,我们没有NOLOCK来避免数据损坏。所以,选择是不是这里的问题。锁定升级到Rowgroup级别导致死锁。我会用等待类型信息 –

回答

0

在我的情况下,死锁情况是由于锁升级发生,因为一些应验都非常大,在10,000s或100K的范围,它是导致锁升级发生在rowgroup水平和一些情况下,页面级别。

我解决了这个问题,在事务开始时有一个临时表,并且处理临时表上的更新,最后在临时表中插入临时表相关的履行信息到这个OrderFulfillments。这个OrderFulfillments也被临时表用来查看个人已经完成了多少次。但是,它是顶部的共享锁而不是独占锁。

通过使用临时表,每个会话都在自己的副本上工作,并发问题得到解决。

1

你呈现NOLOCK是一样的,因为没有锁定...这是不正确。

NOLOCK相当于READUNCOMMITTED。

•READUNCOMMITTED和NOLOCK提示仅适用于数据锁定。

编译期间的所有查询,包括那些READUNCOMMITTED和NOLOCK提示, 获取SCH-S(架构稳定性)锁和 执行。因此,当一个并发的事务在表上保留一个Sch-M(模式修改)锁定时,查询将被阻止。

例如,数据定义语言(DDL)操作在修改表的模式信息之前获取Sch-M 锁。

任何并发查询,包括那些使用READUNCOMMITTED或NOLOCK提示运行的查询,在尝试获取Sch-S锁时都会被阻止。 相反,持有Sch-S锁的查询将阻止尝试获取Sch-M锁的并发 事务。

对于经过 修改的表,不能指定READUNCOMMITTED和NOLOCK插入,更新或删除操作。 SQL Server查询优化器 将忽略FROM子句中的READUNCOMMITTED和NOLOCK提示, 应用于UPDATE或DELETE语句的目标表。

•与设置为ON时 READ_COMMITTED_SNAPSHOT数据库选项读取已提交的隔离级别:

可以减少锁定争,同时保护交易从 脏通过使用该 的下列读取未提交的数据修改。

•SNAPSHOT 隔离级别。有关隔离级别的更多信息,请参阅SET TRANSACTION ISOLATION LEVEL(Transact-SQL)。

https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table

  • 了解您的索引是如何组织可引起如果说,一个select语句需要您的更新修改的同时整个页面阻塞。

  • 限制测试后的变量。

  • 考虑将DML拆分为多个部分。您可能会发现执行表数据并发修改的最佳范围。

+0

更新你,并且停止非常多地使用NOLOCK。优化器通常足够聪明,如果你使用NOLOCK的话,考虑一个不同的ISOLATION策略。 –