我正在创建一个卖票的应用程序,我有一张可用票的表
id | serial | sold
-------------------------------
1 | 000001 | false
2 | 000002 | false
3 | 000003 | true
当用户请求票证时,应用程序选择票证并将其标记为已售出。
我的问题是:如何管理此表并防止向同一个用户出售同一张票,因为他们知道同时会有数百个请求?
我正在考虑锁定但是当行被锁定以进行交易时,如果另一个事务请求锁定它必须等到第一个事务完成并将该行更新为已售出,那么第二个事务将返回该票证已售出。现在,如果发现行已被锁定,如何将第二个事务重定向到另一行?
修改
根据Paul Zahra的评论,我创建了一个存储过程
DECLARE @id varchar(MAX)
SELECT @id = (
SELECT top(1) [Id]
FROM [dbo].[AvailableItems] WITH (ROWLOCK, UPDLOCK)
WHERE ([Sold] = 0) )
UPDATE [dbo].[AvailableItems]
SET [Sold] = 1
WHERE [Id] = @id
SELECT [Id], [Serial], [CreateDate], [AvailableTo]
FROM [dbo].[AvailableItems]
WHERE ([Id] = @id)
但我需要确定如果同时发生两笔交易,第二笔交易将会发生什么?它会跳过这一行并移到下一行吗?或者等待第一笔交易完成,然后选择同一行?
答案 0 :(得分:0)
我会使用一个简单的对象来锁定项目,并确保它是私有/静态的。这将允许在类的所有实例之间共享其状态,同时防止在类外部修改对象。
对于错误处理和锁定,请参阅
In C# how can I safely exit a lock with a try catch block inside?
支持// Log异常锁定将自动释放语句。
代码尚未经过测试,但它应该给你一个良好的开端。
public class NextTicketinSequence
{
private static int _LastTicketNumber;
private static object _TicketLock;
public static NextTicketinSequence()
{
NextTicketinSequence._LastTicketNumber = 0;
}
public static int GetNextTicketNumber()
{
int ticketId = 0;
try
{
lock(_TicketLock)
{
NextTicketinSequence.LoadLastTicketSold();
ticketId = NextTicketinSequence._LastTicketNumber + 1;
}
}
Catch(Exception ex)
{
//Log exception lock will be released automaticaly
}
return ticketId
}
public static void LoadLastTicketSold
{
//Code to get the last ticket marked as sold
}
}