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大牛,为什么语句段一和语句段二的顺序对调后,就不会有重复了。
问题来了,以上语句真得能够保证产生唯一的最大值吗
sql语句单据编号生成防并发的更多相关文章
- C# 生成编号(防并发)
今天抽了点时间,写了一个通用的生成编号的程序! 我的生成规则为年月日+两位编号,即:yyyyMMdd+两位编号,譬如:2018101001 / 2018101002 / 2018101003 首先,一 ...
- MySQL通过SQL语句来直接生成新表
1. 既复制表结构,也复制表数据 mysql> CREATE TABLE tmp_table SELECT * FROM dede_news; 说明:这种方法的缺点就是新表中没有了旧表的prim ...
- 在sqlserver中,使用sql语句更新数据库:生成随机数,更新每一行中的年龄字段
use School --指定数据库 declare @min_id int --声明整数变量@x set @min_id=(select MIN(Id) from Students) --给变量@x ...
- SqlServer 中如何查看某一个Sql语句是复用了执行计划,还是重新生成了执行计划
我们知道SqlServer的查询优化器会将所执行的Sql语句的执行计划作缓存,如果后续查询可以复用缓存中的执行计划,那么SqlServer就会为后续查询复用执行计划而不是重新生成一个新的执行计划,因为 ...
- mysqls,为node.js而编写的sql语句生成插件 (crud for mysql).
It is written in JavaScript,crud for mysql.You can also use transactions very easily. mysqls 一款专为nod ...
- 年终巨献 史上最全 ——LINQ to SQL语句
LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句.Where操 ...
- LINQ to SQL语句大全
LINQ to SQL语句大全 LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判 ...
- 史上最全 ——LINQ to SQL语句
LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句.Where操 ...
- LINQ to SQL语句(17)之对象加载
对象加载 延迟加载 在查询某对象时,实际上你只查询该对象.不会同时自动获取这个对象.这就是延迟加载. 例如,您可能需要查看客户数据和订单数据.你最初不一定需要检索与每个客户有关的所有订单数据.其优点是 ...
随机推荐
- luogu P1107 最大整数
题目描述 设有n个正整数 (n<=20), 将它们连接成一排, 组成一个最大的多位整数. 例如: n=3时, 3个整数13, 312, 343连接成的最大整数为: 34331213 又如: n= ...
- PKUSC2018训练日程(4.18~5.30)
(总计:共66题) 4.18~4.25:19题 4.26~5.2:17题 5.3~5.9: 6题 5.10~5.16: 6题 5.17~5.23: 9题 5.24~5.30: 9题 4.18 [BZO ...
- 【二分答案】【最大流】bzoj1305 [CQOI2009]dance跳舞
http://hzwer.com/1986.html #include<cstdio> #include<algorithm> #include<queue> #i ...
- java web定时任务---quartz
写在前面: 前面有简单的记录下Timer定时的用法,但是在此次项目中,选择的是quartz来完成定时操作任务的.两者都可以完成定时操作,但是spring可以整合quartz,并且配置起来也比较简便,还 ...
- boost 1.57 vs2013 编译
启动vs2013中的命令行注意区分32/64, 进入boost目录, 再次运行 bootstrap.bat 编译: bjam.exe stage --toolset=msvc-12.0 --sta ...
- 小程序与h5的相互跳转
1, 小程序跳h5 <web-view src="https://zgl.seamo.cn/zglh5/kjzjlist1.html"></web-view> ...
- 数据访问与sql语句的管理(一)
在开发过程中数据访问是必不可少的.每个框架都会有自己数据访问机制.大家在一般的情况下会为自己的框架配备2套数据访问机制,ORM和DataHelper.当然,根据项目的需要有时候也可能只一种. 其实这2 ...
- gin框架中间件解决跨域问题
http://www.niu12.com/article/45// 初始化routerrouter := gin.New() router.Use(gin.Logger()) router.Use(g ...
- Linux下使用Python操作MySQL数据库
安装mysql-python 1.下载mysql-python 打开终端: cd /usr/local sudo wget http://nchc.dl.sourceforge.net/sourcef ...
- CentOS7.x 通过mail命令发,使用465端口(smtps协议)发送邮件
#创建证书mkdir -p /root/.certs/echo -n | openssl s_client -connect smtp.qq.com:465 | sed -ne '/-BEGIN CE ...