sql语句单据编号生成防并发

有用户反馈说发现重复单据号,检查发现以下单据号被分配给了不同的两个职工

系统中使用语句exec GetNewOrderNumber 'pwgnumber','PWG',1, @pwg_number output

来产生唯一单据号

此存储过程中获取最大值的语句如下:

复制代码
复制代码
if exists(select * from s_systemset(nolock) where classname=@keyname and typename=@keyvalue)      
  begin      
    begin tran
--语句段1
select @ordernumber=typename+substring(replicate('0',convert(int,8))+itemvalue,
       len(replicate('0',conv     ert(int,8))+itemvalue)-(convert(int,8)-1),convert(int,8))     
    from s_systemset(nolock)    
    where classname=@keyname      
      and typename=@keyvalue      
--语句段2          
    update s_systemset       
    set itemvalue=itemvalue+1    
    from s_systemset        
    where classname=@keyname      
      and typename=@keyvalue      
    commit tran    
  end 
复制代码
复制代码

 

1
同时开两个SQL查询窗口执行以下语句

窗口一:waitfor delay '00:00:05'
print '1'
declare @ordernumber varchar(20),@i int=1,@sysid int=1
while @i<=31000
begin
exec TestNewOrderNumber 'testnumber','TST',1,@ordernumber output 
insert into test_log(docnumber,sysid,indate) 
values (@ordernumber,@sysid,GETDATE())
set @i=@i+1
end

 

窗口二:

waitfor delay '00:00:06'
print '2'
declare @ordernumber varchar(20),@i int=1,@sysid int=2
while @i<=32000
begin
exec TestNewOrderNumber 'testnumber','TST',1,@ordernumber output 
insert into test_log(docnumber,sysid,indate) 
values (@ordernumber,@sysid,GETDATE())
set @i=@i+1
end

 

检查是否有重复:

select docnumber,COUNT(docnumber)
from test_log
group by docnumber
having COUNT(docnumber)>=2

 

测试结果如下:有8条记录重复。

  

 

在两个不同用户同一秒调用此语句后,产生了重复的Pwg_Number,为什么呢?

在SQL中已经用了事务来获取最大值,为何不同用户几乎同时调用时会返回相同的pwg_number?

尝试将语句段1和语句段2对调如下:

复制代码
复制代码
--将语句段1和语句段2对调
begin tran    
    update s_systemset   --语句段2    
    set itemvalue=itemvalue+1    
    from s_systemset        
    where classname=@keyname      
      and typename=@keyvalue 
    --语句段1  
    select @ordernumber=typename+substring(replicate('0',convert(int,8))+itemvalue,len(replicate('0',convert(int,8))+itemvalue)-(convert(int,8)-1),convert(int,8))     
    from s_systemset(rowlock) --将nolock改为rowlock   
    where classname=@keyname      
      and typename=@keyvalue      

    commit tran
复制代码
复制代码

重复在两个窗口并行测试,第一次是9万笔,第二次是90万笔,第3次10万笔。统计没有重复记录。

到这里重复单据号的问题是否算是已经得到解决了呢?

各位SQL大牛,为什么语句段一和语句段二的顺序对调后,就不会有重复了。

 问题来了,以上语句真得能够保证产生唯一的最大值吗

posted @   violety  阅读(423)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示