不错呦!smile@林凯西,确保“准备文件”中的几个文件都有安装,S...您好,看了您这篇帖子觉得很有帮助。但是有个问题想请...我的修改过了怎么还被恶意注册呢 @jjjjiiii 用PJ快9年了,主要是A...PJ3啊,貌似很少有人用PJ了,现在不是WP就是z...@332347365,我当时接入时错误码没有-10...楼主,ChkValue值应为-103是什么意思呢?...大哥 你最近能看到我发的信息,请跟我联系,我有个制...
SQL Server2000使用行锁解决并发库存为负超卖问题
编辑:dnawo 日期:2014-04-16
假设库存表结构及数据如下:
在秒杀等高并发情况下,使用下面的存储过程会导致库存为负产生超卖问题:
这种情况下,我们可以对行使用排他锁(X锁)来解决:
补充说明
[1].不用行锁时,减库存用Quantity=@Quantity-@number问题更严重,不仅仅是为负的问题了;
[2].XLOCK的作用有两点:一是说明锁模式为排他锁,二是延长行锁时间至事务结束。若省略XLOCK仍会产生超卖问题;
[3].锁模式有共享锁(HOLDLOCK)、更新锁(UPDLOCK)和排他锁(XLOCK),考虑将上边XLOCK改为HOLDLOCK结果会怎样?
--------------------------------------------------------------------------------------------------------
有网友提供了另外一种方法,由于update语句本身具有排他锁,因而用下边方法也是可以的:
复制内容到剪贴板
程序代码

create table Stock
(
Id int identity(1,1) primary key,
Name nvarchar(50),
Quantity int
)
--insert
insert into Stock select 'orange',10
(
Id int identity(1,1) primary key,
Name nvarchar(50),
Quantity int
)
--insert
insert into Stock select 'orange',10
在秒杀等高并发情况下,使用下面的存储过程会导致库存为负产生超卖问题:
复制内容到剪贴板
程序代码

create procedure [dbo].Sale
@name nvarchar(50),
@number int,
@result bit output
as
begin tran
declare @Quantity int
select @Quantity=Quantity from Stock where Name=@name
if @Quantity>=@number begin
waitfor delay '00:00:10' --todo
update Stock set Quantity=Quantity-@number where Name=@name
end
if @@rowcount>0 begin
select @result=1
commit
end
else begin
select @result=0
rollback
end
go
@name nvarchar(50),
@number int,
@result bit output
as
begin tran
declare @Quantity int
select @Quantity=Quantity from Stock where Name=@name
if @Quantity>=@number begin
waitfor delay '00:00:10' --todo
update Stock set Quantity=Quantity-@number where Name=@name
end
if @@rowcount>0 begin
select @result=1
commit
end
else begin
select @result=0
rollback
end
go
这种情况下,我们可以对行使用排他锁(X锁)来解决:
复制内容到剪贴板
程序代码

create procedure [dbo].Sale
@name nvarchar(50),
@number int,
@result bit output
as
begin tran
declare @Quantity int
select @Quantity=Quantity from Stock with(ROWLOCK,XLOCK) where Name=@name
if @Quantity>=@number begin
waitfor delay '00:00:10' --todo
update Stock set Quantity=Quantity-@number where Name=@name
end
if @@rowcount>0 begin
select @result=1
commit
end
else begin
select @result=0
rollback
end
go
@name nvarchar(50),
@number int,
@result bit output
as
begin tran
declare @Quantity int
select @Quantity=Quantity from Stock with(ROWLOCK,XLOCK) where Name=@name
if @Quantity>=@number begin
waitfor delay '00:00:10' --todo
update Stock set Quantity=Quantity-@number where Name=@name
end
if @@rowcount>0 begin
select @result=1
commit
end
else begin
select @result=0
rollback
end
go
补充说明
[1].不用行锁时,减库存用Quantity=@Quantity-@number问题更严重,不仅仅是为负的问题了;
[2].XLOCK的作用有两点:一是说明锁模式为排他锁,二是延长行锁时间至事务结束。若省略XLOCK仍会产生超卖问题;
[3].锁模式有共享锁(HOLDLOCK)、更新锁(UPDLOCK)和排他锁(XLOCK),考虑将上边XLOCK改为HOLDLOCK结果会怎样?
--------------------------------------------------------------------------------------------------------
有网友提供了另外一种方法,由于update语句本身具有排他锁,因而用下边方法也是可以的:
复制内容到剪贴板
程序代码

create procedure [dbo].Sale
@name nvarchar(50),
@number int,
@result bit output
as
begin tran
declare @Quantity int
select @Quantity=Quantity from Stock where Name=@name
if @Quantity>=@number begin
waitfor delay '00:00:10' --todo
update Stock set Quantity=Quantity-@number where Name=@name and Quantity>=@number
end
if @@rowcount>0 begin
select @result=1
commit
end
else begin
select @result=0
rollback
end
go
@name nvarchar(50),
@number int,
@result bit output
as
begin tran
declare @Quantity int
select @Quantity=Quantity from Stock where Name=@name
if @Quantity>=@number begin
waitfor delay '00:00:10' --todo
update Stock set Quantity=Quantity-@number where Name=@name and Quantity>=@number
end
if @@rowcount>0 begin
select @result=1
commit
end
else begin
select @result=0
rollback
end
go






评论: 0 | 引用: 0 | 查看次数: 3789
发表评论
请登录后再发表评论!