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

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

  • 相关阅读:
    兴趣遍地都是,专注和持之以恒才是真正稀缺的
    vuecli2和vuecli3项目中添加网页标题图标
    vue+sentry 前端异常日志监控
    从零构建vue项目(三)--vue常用插件
    从零构建vue项目(一)--搭建node环境,拉取项目模板
    dbvisualizer安装
    TS学习笔记----(一)基础类型
    基于weui loading插件封装
    UI组件--element-ui--全部引入和按需引入
    vue_全局注册过滤器
  • 原文地址:https://www.cnblogs.com/Violety/p/9597527.html
Copyright © 2011-2022 走看看