假设SQLServer中的表具有以下结构:
TABLE t (Id INT PRIMARY KEY)
然后,我有一个存储过程,该过程经常被调用,它可以在其他类型的东西中向该表中插入数据:
BEGIN TRAN
DECLARE @Id INT = SELECT MAX(Id) + 1 FROM t
INSERT t VALUES (@Id)
...
-- Stuff that gets a long time to get completed
...
COMMIT
此方法的问题有时是因为遇到2个或更多过程调用并尝试在表上插入相同的ID而导致主键冲突。
我已经能够解决这个问题,在SELECT语句中添加一个制表符:
DECLARE @Id INT = SELECT MAX(Id) + 1 FROM t WITH (TABLOCK)
现在的问题是,对该过程的成功调用必须等待当前正在执行的事务完成才能开始其工作,从而仅允许一个过程同时运行。
仅在执行select和insert语句期间是否有任何建议或技巧来获得锁定?
谢谢。
TABLOCK是一个糟糕的主意,因为您要序列化所有调用(无并发性)。请注意,使用SP时,您将保留运行期间授予的所有锁,直到SP完成。因此,除了实际需要的位置以外,您都希望将锁最小化。