并发操作

king06 2011-01-12 09:50:05
示例存储过程:(设表tb1内字段id,custname,充值金额,当前金额,systemtime),id为标识字段
CREATE PROCEDURE insertA
@mm numeric(18,2),@custname varchar(30)
AS
declare @lm as numeric(18,2)
set @lm=0
begin tran
if exists(select * from tb1 where custname=@custname)
begin
select @lm=当前金额 from tb1 with(updlock,rowlock) where id=(select max(id) from tb1 where custname=@custname)
select @lm=@lm+@mm
end
else
select @lm=@mm

insert into tb1(custname,充值金额,当前金额,systemtime)
values(@custname,@mm,@lm,getdate())

if @@error=0
commit tran
else
rollback tran

GO

若多用户同时操作,可能会出现执行insert语句时取到的@lm(当前金额)相同,
也即两个用户同时执行存储过程,取到的是同一个"当前金额"(实际后一个用户应该取前一个用户新进的"当前金额")
请问如何解决该问题呢? SCOPE_IDENTITY() ?
...全文
168 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
king06 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 jinfengyiye 的回复:]
多个用户同时我想也不会啊。因为custname是不相等的啊。为什么还要锁呢?
[/Quote]
多个用户也可以对同一custname操作呀
wing7742 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wing7742 的回复:]
引用 4 楼 maco_wang 的回复:
1 如何锁一个表的某一行
SQL code

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table ROWLOCK WHERE id = 1


2 锁定数据库的一个表

SQL code
SELECT * FROM table WITH (HOLD……
[/Quote]
这个对数据库版本有要求么?
wing7742 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 maco_wang 的回复:]
1 如何锁一个表的某一行
SQL code

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table ROWLOCK WHERE id = 1


2 锁定数据库的一个表

SQL code
SELECT * FROM table WITH (HOLDLOCK)



……
[/Quote]

这个好收藏起
gw6328 2011-01-12
  • 打赏
  • 举报
回复
多个用户同时我想也不会啊。因为custname是不相等的啊。为什么还要锁呢?
king06 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 maco_wang 的回复:]
2 锁定数据库的一个表


SQL code
SELECT * FROM table WITH (HOLDLOCK)

……
[/Quote]
谢谢~
锁定这个表,还可以让用户读取记录吧;如果不能读取了,那确实是可以达到目的,但我3F说明了相应的问题哦.
这里的需求就是用户操作时要取到最新的,最真实的max(id)
可能我的存储过程思路不该这样,如果别的方法能够实现上述功能也好哇
叶子 2011-01-12
  • 打赏
  • 举报
回复
1 如何锁一个表的某一行

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table ROWLOCK WHERE id = 1


2 锁定数据库的一个表

SELECT * FROM table WITH (HOLDLOCK)  


king06 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 ssp2009 的回复:]
LOCK
[/Quote]
我知道有个表级LOCK,可这个会降低性能了.
因为涉及到的这个表用户操作很频繁,不然出现同时insert的几率也基本上为0哈.
如果行上LOCK可以做到,恳请指教哈,O(∩_∩)O谢谢
快溜 2011-01-12
  • 打赏
  • 举报
回复
LOCK
king06 2011-01-12
  • 打赏
  • 举报
回复
哦,忘说了数据库SQL Server2000
coleling 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 king06 的回复:]
呵呵,说的入理啊.
我的"当前金额"是有在另外一个表里单独存放了的,只是没写上来而已,嘿嘿.
找到一篇文章http://sjweb.hhit.edu.cn/article/show.aspx?id=3947
[/Quote]

既然知道了,那速度结贴三
king06 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 coleling 的回复:]
楼主,你这种情况控制并发有点难度,因为你的表设计有问题,应该将充值记录和当前金额分表存放。

在不修改表设计的情况下,很难彻底解决并发问题(不容易兼顾并发和性能).

你现在的存储过程,其中的事务和锁其实没起什么作用,不如去掉。
其实你现在的过程可以用一条语句实现(对并发稍有缓解):
SQL code
insert into tb1(custname,充值金额,当前金……
[/Quote]
呵呵,说的入理啊.
我的"当前金额"是有在另外一个表里单独存放了的,只是没写上来而已,嘿嘿.
找到一篇文章http://sjweb.hhit.edu.cn/article/show.aspx?id=3947
coleling 2011-01-12
  • 打赏
  • 举报
回复
楼主,你这种情况控制并发有点难度,因为你的表设计有问题,应该将充值记录和当前金额分表存放。

在不修改表设计的情况下,很难彻底解决并发问题(不容易兼顾并发和性能).

你现在的存储过程,其中的事务和锁其实没起什么作用,不如去掉。
其实你现在的过程可以用一条语句实现(对并发稍有缓解):

insert into tb1(custname,充值金额,当前金额,systemtime)
select top (1) @custname, @mm, 当前金额+@mm, getdate()
from (select id, 当前金额 from tb1 where custname=@custname union all select 0, 0) a
order by id desc

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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