zoukankan      html  css  js  c++  java
  • 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大牛,为什么语句段一和语句段二的顺序对调后,就不会有重复了。

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

  • 相关阅读:
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (四) 自动化部署
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (三) 服务观测
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (二) 部署微服务程序
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (一) 部署 Nacos
    C++知识点
    libmkl 学习笔记
    基于tesseract-OCR进行中文识别
    poco编译与运行
    Linux下的I/O复用与epoll详解(转载)
    高并发网络编程之epoll详解(转载)
  • 原文地址:https://www.cnblogs.com/Violety/p/9597527.html
Copyright © 2011-2022 走看看