2012-03-16 57 views
4

我有一个航班预订程序使用mssql ,对于预订航班,我想确定应该使用隔离级别还是锁定?我应该使用哪个隔离级别来预订航班

(这是一个示例代码,我的问题是隔离级别这种情况下不做预订)

我的数据库中有一个表像盘点:

Inventory Table 
------------------------ 
id (Pk), 
FlightNumber, 
Total, 
Sold 

现在如果有的要储备飞行,我用这个代码在交易

Decalre @total int; 
Decalre @sold int; 
Select @total=Total,@sold=Sold From Inventory where FlightNumber='F3241b'; 

IF @[email protected] > 0 
BEGIN 
    Update inventory set Sold=Sold+1 where FlightNumber='F3241b'; 
    PRINT 'Reserve Complete' 
END 
ELSE 
PRINT 'this flight is full' 

我有这些问题:

问题1:我应该使用Locks还是Isolation Levels?它是否对性能有任何好处?

Q2:根据Q1哪个隔离级别或锁定我应该使用

回答

4

如果你正在寻找,看看有什么隔离级别将示例代码的工作,因为它代表,而比解决示例代码所解决问题的最佳方法是什么,您至少需要保证可重复读取。

使用严格的两阶段锁定(S2PL)进行并发的数据库允许READ COMMITTED事务在每个语句完成时或更早时删除共享锁,因此在事务A检查可用性和它声明座位,其他人可以通过事务B来再次阅读,而不会导致任何事务失败。事务A可能会暂时阻止事务B,但两者都会更新,并且可能会被过度销售。

在使用多版本并发控制(MVCC)进行并发的数据库中,读取不会阻止写入和写入不会阻止读取。在READ COMMITTED语句中,每条语句根据已提交的内容使用数据库的新快照,并且至少在某些情况下(我知道PostgreSQL中的情况属实),可以毫无错误地解决并发写入。因此,即使交易A正在更新已售出的计数,或者已经这样做而没有提交,交易B也会看到旧的计数并继续更新。当它尝试更新时,它可能会阻止等待上一次更新,但是一旦提交,它就会找到该行的新版本,检查它是否符合选择条件,如果是,则更新,如果没有,则忽略该行,以及继续进行提交而没有错误。所以,你又一次被过度销售。

我猜答案Q2,如果你选择使用事务隔离。通过修改示例代码来获取显式锁,可以在较低的隔离级别解决问题,但这通常会导致使用隔离级别更严格的阻塞,从而可以自动处理它。

2

你是过分复杂的事情。你所有的查询是可以被替换为:

Update inventory 
set Sold = Sold + 1 
where FlightNumber = 'F3241b' 
AND Total - Sold > 0 -- Important! 

如果航班客满,更新将不会发生(第二个条件不符合),它会返回0修改的行。如果是这种情况,则意味着航班已满。否则,查询将修改Sold值并返回1修改后的行。

在这种情况下,任何隔离级别都可以,因为单个查询总是原子的。这有点类似于

BTW这种查询可以很容易地调整,以允许保留的任意数以原子制成:

Update inventory 
set Sold = Sold + @seats 
where FlightNumber = 'F3241b' 
AND Total - Sold >= @seats 
+0

TanQ但acctualy我的问题是隔离水平,我想出了这个例子,知道我是否想要做类似的事情我该怎么办?你可以回答与原始示例 – 2012-03-16 12:27:01

相关问题