我知道数据读取器和数据集之间的区别。
对于需要优化的只读,快速和仅向前数据访问的应用程序,DataReader是更好的选择。
数据集更适合应用程序,您可以在应用程序级别上获取所有数据并根据需要对其进行更新,然后将更改提交到数据库。
根据我的理解,请清除是否有任何错误。
现在我接受了采访,那里有人问我。数据读取器或互联体系结构是否适合票务系统等应用程序。基本上,她的意思是很多用户可能正在尝试更新同一张表。因此,并发的概念来了。
我们可以使用Disconnected体系结构检查并发性,一次只允许一个用户更新表。但是不知道它如何在连接架构方面发生。与数据库的连接,特别是与相关表的连接是否会使仅一个用户进行更新,而其他稍后尝试访问的用户将无法进行更新。
如果所有用户都打开了连接,它将不会影响性能,因为数据库将达到瓶颈。
我希望我能得到答案以了解他们。
最佳答案
我认为这与哪个更好无关,因为一旦数据到达客户端,它就已经是旧的/无效的了。显示保留表可能有助于大致了解保留的内容,但下一秒可能会完全不同。您想消除比赛条件。一个良好的体系结构是必要的。
一种方法是“保留”票证[1]。应用程序要求获取在匹配条件下可用的票证。在这一点上,有关该票证是否可用的已知事实。如果可用,它也已经被保留。这样可以避免多次预订一张票。下一次保留(相同的操作/动作)将导致保留其他票证。如果需要,您以后总是可以在此票证中添加信息(例如,票证所有者及其信息)。没有附加任何信息的票证,将在一定时间后超时,并返回到池中。这些票可以再次“保留” [1]。
[1]为避免多次分配,请使用optimistic locking。
要回答这个问题,我会说DataReader
。它将数据库通信保持在最低限度(加载和锁定),因此可以尽快处理更新。只需记住彼此选择并不能解决并发问题。至关重要的是整体解决方案。
示例
我不知道要求,但是由于这是一个面试问题,我将举一个例子。不要把这当作黄金法则,但是从我的头顶掉下来会是这样的:
(如果需要)首先,向用户显示一个屏幕,其中显示系统中还有剩余可保留的票证。打开一个连接,然后阅读器读取可用于预订的门票数量。关闭阅读器和连接。用户进入下一个屏幕。
SELECT COUNT(*)
FROM [Tickets]
WHERE ([LastReserved] IS NULL OR [LastReserved] <= DATEADD(MINUTE, GETDATE(), @ticketTimeout))
AND [TickedAssignedToUserId] IS NULL;
用户请求x数量的票证并进入下一个屏幕。此时,系统将以乐观锁定检查是否有足够的票证。只需打开一个连接(带有事务!)并执行以下查询:
UPDATE TOP(@numberOfTicketsRequested) [Tickets]
SET [LastReserved]=GETDATE()
WHERE ([LastReserved] IS NULL OR [LastReserved] <= DATEADD(MINUTE, GETDATE(), @ticketTimeout))
AND [TickedAssignedToUserId] IS NULL;
受影响的行数应与@numberOfTicketsRequested相同。如果是这种情况,请提交交易并获取票证标识符。否则回滚并告诉用户不再有票证。此时,我们需要记录信息,因此您可能还需要获取标识符。
此时,用户将获得
@ticketTimeout
分钟的时间来输入其用户详细信息。如果正确完成,则可以执行以下查询:UPDATE TOP(@numberOfTicketsRequested) [Tickets]
SET [TickedAssignedToUserId]=@userId
WHERE [TicketId]=@Id AND [LastReserved]=@lastReserved AND [TickedAssignedToUserId] IS NULL;
如果用户花费了超过10分钟的时间,而其他人又再次请求了同一张票证,则
LastReserved
时间戳已更改。当第一个用户尝试使用其详细信息预订票证时,该更新不再与原始LastReserved
时间戳匹配,并且该更新将显示受影响的行不足(=回滚)。如果与受影响的行数匹配,则用户成功预订了票证(= commit)。请注意,除票证标识符外,没有票证信息到达应用程序。我也没有包含用户注册。没有传递完整的表,并且锁的使用最少(仅用于两次简短更新)。