mysql生成编码并发处理_sql语句单据编号生成防并发

在MySQL中,用户遇到并发环境下生成单据编号重复的问题。文章通过分析存储过程,展示了在并发调用同一SQL语句时,如何由于事务顺序导致重复编号的生成。通过对语句段的调整,问题似乎得到了解决,但作者提出了疑问,是否这样就能确保生成唯一的最大值。文章探讨了SQL并发控制在防止重复单据号中的作用。
摘要由CSDN通过智能技术生成

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

c9399d59f32dbe7ccbb34dea9b1032cb.png

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

来产生唯一单据号

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

48304ba5e6f9fe08f3fa1abda7d326ab.png

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

48304ba5e6f9fe08f3fa1abda7d326ab.png

窗口一: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条记录重复。

45405b5c0c70b40cc5e04b43c0e090e3.png

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

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

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

48304ba5e6f9fe08f3fa1abda7d326ab.png

--将语句段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

48304ba5e6f9fe08f3fa1abda7d326ab.png

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

c1449dadd39d76db7c67756b614bbaac.png

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值