求助! 存储过程并发执行的问题 。全部100分奉上 谢谢

emailwxt 2017-04-27 01:11:38
初次写存储过程,不知道这样写对不对


库存表a ,id 主键自增 pid 商品id(int) aa 库存量(int) cc 库存状态(int)
id pid aa cc
1 2 20 0
2 3 30 1

存储过程1

begin transaction --- 事物开始

select @i=aa ,@cc=cc from a ROWLOCK where id=@id
if @cc=0
begin
if @i>10
begin
update a WITH(ROWLOCK ) set aa=aa-@b ,@c=aa-@b where id=@id
set @error=@@error+@error
if @c>0
begin
set @state=0 -- 正常更新库存
end
else
begin
set @state=2 --更新的aa 小于等于0时 库存不足 事务回滚

end

end
else
begin
update a WITH(ROWLOCK ) set cc=1 where id=@id
set @error=@@error+@error
set @state=1 --库存小于底线 不允许再出货
end
end
else
begin
set @state=3 --库存小于底线 不允许再出货通知管理员补库存
end


================================================================================================


存储过程2
begin transaction --- 事物开始
update a WITH(ROWLOCK) set aa=aa-@b ,@c=aa-@b where id=@id

set @error=@@error+@error
if @error>0
begin
rollback transaction
end
else
begin
if @c>10
begin
commit transaction --当更新后的库存大于10 可以提交
end
else
begin
rollback transaction
end

end

================================================================================================

存储过程3 ------ 还库存
begin transaction --事务开始
select @i=aa ,@cc=cc from a ROWLOCK where id=@id


if @cc=1
begin
if (@i+@b)>10
begin
update a with(rowlock) set aa=aa+@b ,cc=0 where id=@id
set @error=@@error+@error
end
else
begin
update a with(rowlock) set aa=aa+@b where id=@id
set @error=@@error+@error
end
end
else
begin
update a with(rowlock) set aa=aa+@b where id=@id
set @error=@@error+@error
end

================================================================================================
存储过程4 ----管理员修改库存
begin transaction --事务开始
select @i=aa ,@cc=cc from a ROWLOCK where id=@id
update a with(rowlock) set aa=@b where id=@id
set @error=@@error+@error
================================================================================================

存储过程5 ----普通查询
begin transaction --事务开始
select * from a NOLOCK where id=@id


初次写存储过程,不知道这样写对不对。


实际当中这些存储过程可能是按顺序执行 也可能是多用户并发时执行会发生死锁 这种情况该怎么解决,
希望高手们给改改代码或思路或者重新写该怎么写 谢谢
...全文
205 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
emailwxt 2017-04-28
  • 打赏
  • 举报
回复
这个问题应该是Timestamp 的思路,版主的思路也很不错都用的上,谢谢二位,就此结帖
顺势而为1 2017-04-27
  • 打赏
  • 举报
回复
如果使用 Timestamp 第二人更新失败怎么办,让第二个人再从新提交一下?, 因在此期间有人修改且保存数据,因此此次的修改应放弃. 需重新调入数据修改. 那在第二个人提交的时候由于某种原因又并发从而导致更新失败这样循环下去怎么处理。 这种处理方法, 不会存在这样的问题.
顺势而为1 2017-04-27
  • 打赏
  • 举报
回复
这个处理原理是 修改行数据时,将行记录及此行的Timestamp值都读取出来, 读取的行记录放到前端修改, 更新时, 取出最新的Timestamp值与之前读取的前端Timestamp比较, 如果不同,说明此记录已被另一用户修改保存. 比如: 甲和乙碰巧取出同一条记录到前端修改, 此时两人取到前端的Timestamp值相同, 如果甲先保存数据, 那么此条记录的Timestamp就发生了变化, 然后当乙再保存时取出的记录Timestamp值就会与之前的不同, 程序就提示此记录已被其它用户修改保存, 必须放弃保存, 否则就overwrite 了甲修改.
emailwxt 2017-04-27
  • 打赏
  • 举报
回复
感谢appetizing_fish1 的回复 如果使用 Timestamp 第二人更新失败怎么办,让第二个人再从新提交一下?,那在第二个人提交的时候由于某种原因又并发从而导致更新失败这样循环下去怎么处理。
卖水果的net 2017-04-27
  • 打赏
  • 举报
回复
提供一个思路: 如果 num 大于 100 ,则 num -100 update t set num = num - 100 where id = @id and num >= 100 if @@rowcount > 0 then 成功, else 失败,提示已小于 100 end
顺势而为1 2017-04-27
  • 打赏
  • 举报
回复
你这种写法是悲观锁, 再说也没有必要在SQL 语句中带上rowlock,nolock之类的, SQL SERVER会自动确定用什么锁. 我现在是用Timestamp字段实现乐观锁, 有效处理并发.

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧