如何锁定和解锁SQL SERVER表?

5

为了避免解释不清我的问题,我会尽量提供更多信息。

我正在创建一个批量上传过程,可以将数据插入到两个表中。这两个表大致如下。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、索引等。它们是Parts_StagingDescription_Staging
Parts_Staging中,有一个额外的列,包含层次结构节点字符串,这是这种格式的HierarchyNode:/1/2/3/等。然后当数据从_Staging表复制到实际表时,我使用CAST(Source.Column AS hierarchyid)
由于在两个表之间共享的ID的复杂性,自引用ID和Parts中的层次结构ID以及要插入的行数(可能在10万以上),我决定100%先在C#模型中编译所有数据,包括PK ID。所以在C#中,该过程如下:
1.查询两个表的MAX ID 2.使用这些Max ID,编译两个表的所有数据的完整模型(包括层次结构/1/2/3/) 3.对两个_Staging表进行批量插入 4.触发一个SP,将两个_Staging表中的非重复数据复制到实际表中。(这是CAST(Source.Column AS hierarchyid)发生的地方)。
我们正在导入许多零件手册,单个零件可能会在多本书中复制。我们需要删除重复项。在第4步中,通过检查Parts表中的SourcePartIdDescription表中的DescriptionText中的Description来除去重复项。
整个过程运行得很好!而且最重要的是,它非常快。但是,如果您仔细阅读此内容(我感谢您),则已经注意到一个明显的问题。
如果同时进行多个进程(这绝对会发生!),那么存在非常真实的风险,即ID混乱并且数据变得非常损坏。Process1可以执行GET MAX ID查询,并在完成之前,Process2也可以执行GET MAX ID查询,因为Process1实际上还没有写入表,所以它将获得相同的ID。
我最初打算使用SEQUENCE对象,而最初的计划似乎非常出色。但在测试中它瓦解了,因为同一数据有可能会被处理多次,并且在从_Staging表复制到最终表时被忽略。在这种情况下,SEQUENCE数字将已经被占用和使用,导致ID中存在巨大的间隙。虽然这不是致命缺陷,但我们宁愿避免这个问题。
所以...这是一个很长的背景信息,要问这个实际问题。我想做的是:
  1. 锁定两个相关的表
  2. 按上述步骤执行步骤1-4
  3. 解锁这两个表。
锁需要是读锁(我认为是独占锁?)这样如果另一个进程尝试执行 “GET MAX ID”查询,那么它就需要等待。
我的问题是:1)这是最好的方法吗?2)如何在表上放置排他锁?
谢谢!

这个过程根本不起作用。将数据处理移动到客户端会增加延迟,而不是减少延迟。使用MAX(ID)计算ID会引入重复ID的风险,不仅在多个处理时,还在某些行被删除时。在这种情况下,不会出现任何错误,但一些新值将接收已被删除条目使用的ID,并与错误记录相关联。 - Panagiotis Kanavos
2
每当您认为需要锁定表时,都应考虑整个过程是否也存在问题。锁定是用于短期操作的。它们不是签入/签出机制。 - Panagiotis Kanavos
好的,谢谢Panagiotis。我听到你了。我可以问一下你会如何完成整个过程吗? - Casey Crookston
表A充满了卡车和汽车零件。 表B中的描述可以用英语或日语表示。在源数据即CSV中,零件和描述均为1:1,并且许多描述重复。因此,对于表A,我们使用PartID检查重复,在表B中,我们使用字符串即描述。问题是很多零件在我们导入的书籍中都是重复的。当我们导入多本书时,我们只想将零件目录化一次。 - Casey Crookston
1
简短版:这是一个经典的案例,需要在同一事务中插入多个父级和多个子级。长版:阅读我对类似案例的回答,找出相似之处,根据您的具体情况修改提出的解决方案,然后去泡一杯值得庆祝的咖啡吧。 - Zohar Peled
显示剩余11条评论
1个回答

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接