【问题标题】:Which Isolation level should i use for booking flight我应该使用哪种隔离级别来预订航班
【发布时间】:2012-03-16 12:09:39
【问题描述】:

我有一个使用 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 @total-@sold > 0
BEGIN
   Update inventory set Sold=Sold+1 where FlightNumber='F3241b';
   PRINT 'Reserve Complete'
END
ELSE
PRINT 'this flight is full' 

我有这些问题:

Q1:我应该使用锁还是隔离级别?使用一个对性能有什么好处吗?

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

【问题讨论】:

    标签: isolation-level


    【解决方案1】:

    如果您希望了解哪种隔离级别可以使示例代码按原样工作,而不是解决示例代码解决的问题的最佳方法,您将需要至少可重复读取的保证.

    对并发使用严格的两阶段锁定 (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!
      

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

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

      顺便说一句,可以轻松调整此查询以允许原子地进行任意数量的预订:

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

      【讨论】:

      • TanQ 但实际上我的问题是隔离级别,我想出了这个例子来知道我是否想做类似的事情我应该怎么做?你能用原来的例子回答
      【解决方案3】:

      请参阅此链接,该链接解释了 SQL Server 中的 SNAPSHOT ISOLATION 级别。 http://msdn.microsoft.com/en-us/library/ms345124(v=sql.90).aspx

      他们谈论汽车租赁应用程序。

      如果您需要更严格的隔离级别,您可以移至 IsolationLevel Serializable。但请注意,这很容易被锁定并可能影响您的性能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-05
        • 1970-01-01
        • 2016-12-29
        • 2011-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多