如何锁定和解锁SQL SERVER表?

Cas*_*ton 5 .net c# sql-server sql-server-2017

冒着过度解释我的问题的风险,我将在过多信息方面犯错。

我正在创建一个将数据插入两个表的批量上传过程。这两个表大致如下。 TableA是允许N个参考级别的自参考表。

Parts (self-referencing table)
--------
PartId (PK Int Non-Auto-Incrementing)
DescriptionId (Fk)
ParentPartId
HierarchyNode (HierarchyId)
SourcePartId (VARCHAR(500) a unique Part Id from the source)
(other columns)

Description
--------
DescriptionId (PK Int Non-Auto-Incrementing)
Language (PK either 'EN' or 'JA')
DescriptionText (varchar(max))
Run Code Online (Sandbox Code Playgroud)

(我也应该注意,还有其他表将引用我们暂时不涉及的表PartID 。)

Description,的组合DescriptionLanguage将是独一无二的,但实际`DescriptionID总会有至少两个实例。

现在,对于批量上传过程,我创建了两个临时表,它们看起来很像PartsDescription但是没有任何PK,索引等。它们是Parts_StagingDescription_Staging

Parts_Staging其中有一个额外的列,其中包含一个层次结构节点字符串,它是这种格式的HierarchyNode:/1/2/3/等等。然后,当数据从_Staging表复制到实际表时,我使用CAST(Source.Column AS hierarchyid)

由于在两个表中共享ID的复杂性,中的自引用ID和architectureid Parts以及要插入的行数(可能是100,000个),我决定100%编译其中的所有数据。首先是C#模型,包括PK ID。因此,该过程在C#中如下所示:

  1. 在两个表中查询MAX ID
  2. 使用这些最大ID,为两个表编译所有数据的完整模型(包括/ archiveid / 1/2/3 /)
  3. 在两个_Staging表中进行批量插入
  4. 触发一个SP,该SP将两个_Staging表中的非重复数据复制到实际表中。(这就是CAST(Source.Column AS hierarchyid)发生的地方)。

我们正在导入大量零件书,并且单个零件可以在多本书中复制。我们需要删除重复项。在步骤4,重复进行通过检查淘汰SourcePartIdParts表和DescriptionDescriptionTextDescription表中。

整个过程效果很好!最重要的是,它确实非常快。但是,如果您仔细阅读了这篇文章(非常感谢),那么您已经注意到一个明显的明显问题。

如果同时发生多个进程(并且绝对会发生!),那么就很有可能会混淆ID并导致数据真正损坏。Process1可以执行GET MAX ID查询,并且在完成之前,Process2也可以执行GET MAX ID查询,并且由于Process1尚未实际写入表中,因此它将获得相同的ID。

我最初的想法是使用SEQUENCE对象。一开始,该计划似乎很出色。但是它在测试中失败了,因为完全有可能对同一数据进行不止一次处理,并且在从_Staging表到最终表的复制发生时最终将其忽略。在那种情况下,SEQUENCE号将已经被声明和使用,从而导致ID的巨大缺口。这并不是致命的缺陷,而是我们宁愿避免的问题。

所以...这是很多背景信息,可以问这个实际问题。我想做的是这样的:

  1. 锁定两个有问题的表
  2. 如上所述的步骤1-4
  3. 解锁两个表。

该锁将需要是READ锁(我认为这是互斥锁?),以便如果另一个进程尝试执行GET MAX ID查询,则必须等待。

我的问题是:1)这是最好的方法吗?2)如何在表上放置排他锁?

谢谢!

小智 3

我不确定什么是最好的方法,但就在表上放置“独占”锁而言,只需在查询中使用 with (TABLOCKX) 就会在表上放置一个锁。

如果你想了解它;

https://msdn.microsoft.com/en-GB/library/ms187373.aspx