TABLOCK和HOLDLOCK足以防止INSERT吗?

3

我有一个涉及多个表的事务。在我从EDITED_TABLE中删除一些记录后,我需要防止向TABLE_TO_BE_LOCKED插入数据。目前我正在使用TABLOCKX

DELETE EDITED_TABLE FROM EDITED_TABLE
left join TABLE_TO_BE_LOCKED  with (TABLOCKX) on ....
 WHERE ...

我需要防止向TABLE_TO_BE_LOCKED插入新记录,但我希望保留读取它的可能性。在DELETE后,TABLE_TO_BE_LOCKED仍未更改,这是显式锁定的原因。
我能否使用TABLOCK, HOLDLOCK代替TABLOCKX
注:
我知道如何锁定SQL中的表以进行插入操作?。但是有一个结果不要这样做以防止主键重复。

为什么不直接使用 SELECT FOR UPDATE 和事务呢? - millimoose
@millimoose:在SQL Server中不存在。 - gbn
1个回答

5
如果在事务中对表进行了写操作,则会持有独占锁直到事务结束。在这种情况下,除非在SELECT上使用NOLOCK,否则无法启用SELECT,但是这样会看到已删除的行。
TABLOCK,HOLDLOCK将仅将整个表独占锁定直到事务结束。
听起来你正在尝试修复你选择的解决方案:有了更多信息,我们可能能够提供一个更好的解决方案,而不需要锁提示。例如,如果您的事务需要一致的视图来查看未受其他插入事务影响的已删除数据,则可以尝试以下一个或多个:
- 使用OUTPUT子句处理您开始的数据集 - 仅使用SERIALIZABLE以保留范围(顺便说一下,这是HOLDLOCK) - 使用快照隔离模式 评论后...
BEGIN TRAN

SELECT *
INTO #temp
FROM TABLE_TO_BE_LOCKED
WHERE .. -- or JOIN to EDITED_TABLE

DELETE EDITED_TABLE FROM EDITED_TABLE
left join #temp  with (TABLOCKX) on ....
 WHERE ...

-- do stuff with #temp

COMMIT

@IvanH:谢谢。为什么你想让TABLE_TO_BE_LOCKED不能插入数据?是因为之后要读取吗? - gbn
它稍后在事务中进行处理,但我需要确保在使用它的期间没有新记录。 - IvanH
表格可以包含几十条(甚至数百条)记录。我认为将其复制以进行预计运行1秒的事务并不是非常有效的。EDITED_TABLE是临时的。我需要保留TABLE_TO_BE_LOCKED的状态。 - IvanH
也许我表达不太准确,但我需要阻止其他的写入者(我知道自己在做什么)。 - IvanH
你能把最后一句话加到答案里吗?我接受它。 - IvanH
显示剩余4条评论

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