多用户并发insert,如何保证只能insert一条记录?

fj_2008 2010-05-10 06:59:07
做商城网站,需要实现商品抢购功能,即第一个用户抢购到商品后,其他的用户就不能再抢购了,
用存储过程实现insert,今天居然被测试出多个用户抢购到了商品,存储过程如下,请大虾们指点下如何才能保证表里只能
存一条符合条件的记录:

---------------------------------------------------
CREATE Procedure spShoppingCartAddItem_s
(
@customerid varchar(10),
@ProductID INT,
@Quantity INT,
@DateTimed varchar(20)
)
As
DECLARE @CountItems int
SELECT
@CountItems = Count(ProID)
FROM
ShoppingCart_s
WHERE
ProID = @ProductID
And
convert(varchar(10),dateTimed,120)=@DateTimed
IF @CountItems = 0 /* 只允许有一人抢购到 */
begin
INSERT INTO ShoppingCart_s
(
customerid,
Quantity,
ProID,
DateTimed
)
VALUES
(
@customerid,
@Quantity,
@ProductID,
getdate()
)
end


GO
...全文
435 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
oceantang 2011-03-15
  • 打赏
  • 举报
回复
加个标记字段。。。
coleling 2011-03-15
  • 打赏
  • 举报
回复
只有40分,看来楼主并不着急,只是随便问问......
XiangZhiLiu 2011-03-15
  • 打赏
  • 举报
回复
这是业务上的问题吧,所以不要给数据库增加负担了!
jdhlowforever 2011-03-15
  • 打赏
  • 举报
回复
共同关注,可楼主应该不关注了。2011了
happytojacky 2011-03-14
  • 打赏
  • 举报
回复
请问如何建立一个抢购表?内容是什么?
rfq 2010-05-15
  • 打赏
  • 举报
回复
如果需要可以用排他锁
如果需要别人可以事务内保持共享锁

jxwangjm 2010-05-14
  • 打赏
  • 举报
回复
建立一个抢购表,在表上建唯一索引,
在抢购存储过程中,必须更新抢购表,所以第二个抢购人员一定会失败并且回滚
realclimax 2010-05-14
  • 打赏
  • 举报
回复
begin tran应该就可以了吧。
v1ctory1216 2010-05-14
  • 打赏
  • 举报
回复
按照时间来取呢?取时间最小的!然后第二个时间以后输出个'商品已卖出'
jenhon 2010-05-10
  • 打赏
  • 举报
回复
在INSERT里面加一个触发器,如果条件不成立,则Rollback Transaction。
fj_2008 2010-05-10
  • 打赏
  • 举报
回复
所以,如果标记是做在数据库里,根本就没有用
fj_2008 2010-05-10
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dawugui 的回复:]
引用 4 楼 fj_2008 的回复:
引用 2 楼 dawugui 的回复:
我提个思路,加个标记,第一个人抢到后,设置标记为Y,则其他用户不能抢了.

----
今天就是在毫秒级里被二个人抢购了,
也就是毫秒级里有二个人触发了存储过程...

你加了标记后不存在时间的问题,先到先取.
[/Quote]
--------------
并发,也就是说先读取的用户数据还没insert进去的瞬间,另一个用户也insert了,结果产生了相差毫秒级的数据
dawugui 2010-05-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 fj_2008 的回复:]
引用 2 楼 dawugui 的回复:
我提个思路,加个标记,第一个人抢到后,设置标记为Y,则其他用户不能抢了.

----
今天就是在毫秒级里被二个人抢购了,
也就是毫秒级里有二个人触发了存储过程...
[/Quote]
你加了标记后不存在时间的问题,先到先取.
htl258_Tony 2010-05-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 fj_2008 的回复:]
SQL77:
加锁了后需要解锁吗?
还是过程执行完就自动释放了?
会不会引起其他用户无法select的问题?
[/Quote]不用解,用完会自释放
fj_2008 2010-05-10
  • 打赏
  • 举报
回复
SQL77:
加锁了后需要解锁吗?
还是过程执行完就自动释放了?
会不会引起其他用户无法select的问题?
SQL77 2010-05-10
  • 打赏
  • 举报
回复
BEGIN TRAN
DECLARE @CountItems int
SELECT
@CountItems = Count(ProID)
FROM
ShoppingCart_s WITH(XLOCK,HOLDLOCK)
WHERE
ProID = @ProductID
And
convert(varchar(10),dateTimed,120)=@DateTimed
IF @CountItems = 0 /* 只允许有一人抢购到 */
begin
INSERT INTO ShoppingCart_s
(
customerid,
Quantity,
ProID,
DateTimed
)
VALUES
(
@customerid,
@Quantity,
@ProductID,
getdate()
)
end
COMMIT TRAN

可以在ProID 加上索引,查询时就会自动加上键范围锁定,不会读错
fj_2008 2010-05-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dawugui 的回复:]
我提个思路,加个标记,第一个人抢到后,设置标记为Y,则其他用户不能抢了.
[/Quote]
----
今天就是在毫秒级里被二个人抢购了,
也就是毫秒级里有二个人触发了存储过程...
htl258_Tony 2010-05-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dawugui 的回复:]
我提个思路,加个标记,第一个人抢到后,设置标记为Y,则其他用户不能抢了.
[/Quote]不错
dawugui 2010-05-10
  • 打赏
  • 举报
回复
我提个思路,加个标记,第一个人抢到后,设置标记为Y,则其他用户不能抢了.
htl258_Tony 2010-05-10
  • 打赏
  • 举报
回复
--try
CREATE Procedure spShoppingCartAddItem_s
(
@customerid varchar(10),
@ProductID INT,
@Quantity INT,
@DateTimed varchar(20)
)
As
begin tran
DECLARE @CountItems int
SELECT
@CountItems = Count(ProID)
FROM
ShoppingCart_s
WHERE
ProID = @ProductID
And
convert(varchar(10),dateTimed,120)=@DateTimed
IF @CountItems = 0 /* 只允许有一人抢购到 */
begin
INSERT INTO ShoppingCart_s
(
customerid,
Quantity,
ProID,
DateTimed
)
VALUES
(
@customerid,
@Quantity,
@ProductID,
getdate()
)
end
commit

GO

34,590

社区成员

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

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