我有一张桌子,有两列
key -> Primary Key, auto incremented
reqNumber -> This is a custom generated value
reqNumber的结构为年/月/日/数字,其中number是当天发出请求的次数。例如,如果今天发出了3个请求,昨天发出了2个请求,则该表将具有
key reqNumber
1 2013/07/16/001
2 2013/07/16/002
3 2013/07/17/001
4 2013/07/17/002
5 2013/07/17/003
我遇到的问题是有时多个用户同时保存。执行保存的proc,首先检查今天创建了多少,然后再添加1,所以对于上面的内容,它会看到今天创建了3个,所以下一个将是4.之后它会插入。
但如果两个用户同时点击保存,则他们都获得4,这意味着当插入发生时,我得到2013/07/17/004两次。
有没有办法在SQL或.Net中避免这种情况?锁是唯一的方法,那些会降低性能的正确性吗?
答案 0 :(得分:3)
如果您希望应用程序能够扩展,那么您将需要创建一个新表:
CREATE TABLE DayCounter (
LastReset DateTime NOT NULL,
NextValue INT NOT NULL
)
然后,您需要FUNCTION
,以便随意获取下一个可用值:
CREATE FUNCTION NextCounter()
RETURNS CHAR(3)
AS
BEGIN
BEGIN TRANSACTION
DECLARE @LastReset DATETIME
DECLARE @NextValue INT
SELECT @LastReset = LastReset FROM DayCounter
IF (DATEPART(DAY, DATEADD(DAY, 1, @LastReset)) = DATEPART(DAY, GETDATE())
UPDATE DayCounter SET LastReset = GETDATE(), NextValue = 1
SELECT @NextValue = NextValue FROM DayCounter
UPDATE DayCounter SET NextValue = NextValue + 1
COMMIT TRANSACTION
RETURN RIGHT('000' + CAST(@NextValue AS CHAR), 3)
END
所以现在你可以构建一个更新语句,将你的值串起来,但是它可以安全地从冲突和管理每天的重置。
答案 1 :(得分:1)
首先,我会围绕选择和更新进行交易。
其次我只会使用乐观断开锁定(意为update table where key = TheKey and reqNumber = TheValueYouSelectedToCount
)进行更新,并确保更新了一行。如果你有0行更新,这意味着其他人已经更新了它。
这样您就无法“松散”更新
答案 2 :(得分:1)
如果reqNumber必须是唯一的,那么数据库应该对列具有UNIQUE
约束。添加此选项可为您提供另一种选择:在没有锁定的情况下尝试一次,如果插入失败,请使用锁定再次尝试。凭借高读/写比率和低冲突频率,这可以比每次交易的解决方案执行得更好。