我有一个 MS Sql 函数,它有一些逻辑来处理元素的下一个 ID(根据一些业务逻辑将字母与数字连接,也基于 select count())。
不知何故,在最后几天(在生产环境中),由于系统正在被更多并发用户使用,我们得到了一些双打。
现有的逻辑很简单:
insert into XXXX (A,B,C,D,E)
select dbo.GiveMeNewID(getdate()), @ParamB, @ParamC, @ParamD, @ParamE
不知何故,GiveMeNewId 在两个并行请求中返回了相同的 ID。
这个功能目前在不同的地方使用,在一个存储过程中,也来自“C#客户端”的“动态”SQL构建。
我不想在某些中间人软件中实现“单例”层。
关于如何解决这个问题的任何想法?谢谢。
PS:为了测试,我在 SQL 函数中有以下几行,以便我在不同的窗口中运行不同的插入。
/*********************************************************/
declare @dtStart datetime=getutcdate()
while datediff(second,@dtStart,getutcdate()) < 10
begin
set @dtStart = @dtStart
end
/*********************************************************/
在我的测试场景中,我认为我可以通过编写来解决这个问题:
至少现在我无法复制重复的条目,但我不确定我是否在制造一些我不知道的问题。
如果您认为这不是解决方案,请告诉我。
除了处理您提到的对表本身的独占访问之外,您还可以使用
sp_getapplock
.不使用事务的示例,在会话级别锁定。
或者
带有事务的虚拟示例,在事务级别锁定。
在一个会话中运行此查询(请记住,事务将保持打开状态)
在另一个会话中运行相同的
第二个会话将被阻止,直到事务完成。
不要忘记
COMMIT TRAN
在两个会话中运行。额外的
根据函数中的逻辑,如果您想在使用 datetime 数据作为参数时降低重复的几率,您可以开始使用
datetime2
datetype 和SYSDATETIME()
函数调用来获得更大的时间范围。