如何锁定和解锁SQL SERVER表?

时间:2019-03-07 15:36:37

标签: c# .net 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))

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

Description中,DescriptionLanguage的组合将是唯一的,但是实际的“ DescriptionID”将始终至少具有两个实例。

现在,对于批量上传过程,我创建了两个登台表,它们看起来很像PartsDescription,但没有任何PK,索引等。它们是{{1} }和Parts_Staging

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

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

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

我们正在导入很多零件书,并且单个零件可以在多本书中复制。我们需要删除重复项。在步骤4中,通过检查CAST(Source.Column AS hierarchyid)表中的SourcePartIdParts表中Description的{​​{1}}清除重复项。

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

如果同时发生多个进程(并且绝对会发生!),那么就很有可能会混淆ID并造成数据真正损坏。 Process1可以执行DescriptionText查询,在设法完成之前,Process2也可以执行Description查询,并且因为Process1尚未实际写入表中,所以它会获得相同的ID。 / p>

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

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

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

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

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

谢谢!

1 个答案:

答案 0 :(得分:3)

我不确定哪种方法最好,但是就在表上放置“排他”锁而言,仅在查询中与(TABLOCKX)一起使用会在表上放置一个。

如果您想了解它;

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