我有一个从业务代码调用的存储过程。该代码使用并行性,因此根据某些条件,此SP的多个实例可以同时运行。
我只想执行一次此SP中的某些逻辑。我有一个表(我们称它为HISTORY),其中包含运行的UID和执行此部分代码时的DATETIME。这是我的流程:
SP BEGIN
-- some logic
IF certain conditions are met, check if HISTORY does not have an entry for the UID
1. Add an entry in HISTORY for the current UID
2. Run the once only code
SP END
问题是,有时,如果不同的实例同时到达该部分,则上面的逻辑有时仍会多次执行。我该怎么做才能确保它只能运行一次?
谢谢!
BEGIN TRANSACTION;
INSERT [HISTORY](UID, ...)
SELECT @UID, ...
WHERE NOT EXISTS (
SELECT * FROM [HISTORY] WITH (HOLDLOCK) WHERE UID = @UID
);
IF @@ROWCOUNT = 1 BEGIN;
-- we inserted, do logic that should run only once
END;
COMMIT;
HOLDLOCK
(等同于在之下运行事务SERIALIZABLE
,但更细粒度)可确保没有其他并行运行的事务可以HISTORY
为该UID插入条目;任何尝试这样做的事务都将阻塞,直到第一个事务INSERT
完成然后再返回(因为已经存在一行)。确保UID
存在一个索引,否则它将锁定比正常运行更多的锁定。
像这样正确地获取代码总是很棘手,因此请确保在实践中通过对相同(和不同)UID的并发插入进行压力测试来对其进行测试。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句