竞争条件UPDATE修改信用列 - 回滚时会发生什么?

时间:2010-11-19 23:04:55

标签: sql-server-2005 transactions race-condition rollback

好吧,我试过搜索并且没有找到答案 - 我很好奇ROLLBACK如何处理竞争条件。例如:

如果我有一个表(CompanyAccount),它跟踪公司可以购买的信用额度(每个公司的数据库表中只有一行),并且可能有多个来自同一公司的用户可以减少来自单一公司账户的信用,当ROLLBACK发生错误时会发生什么?

示例:

假设:我已正确编写更新以计算“信用”新余额,而不是猜测新的信用余额是什么(即我们不会尝试告诉UPDATE语句新的贷方余额/价值是多少,我们比如拿信用栏中的任何内容并在UPDATE语句中减去我的减量值... ...

这是一个如何编写update语句的例子:

更新dbo.CompanyAccount            SET Credit = Credit - @DecrementAmount          WHERE CompanyAccountId = @CompanyAccountId

如果“信用”栏有10,000个学分。用户A导致减少4,000个筹码,而用户B导致减少1000个筹码。由于某种原因,在用户A减少期间会触发回滚(在TRANSACTION期间,大约有多达1/2个表的行被INSERTED)。如果用户A赢得竞争条件且新余额为6,000(但尚未COMMIT),如果在应用回滚之前发生用户B的减量,会发生什么?平衡栏是否从6,000到5,000,然后获得ROLLBACK到10,000?

我不太清楚ROLLBACK将如何处理这个问题。也许我过度简化了。有人可以告诉我,如果我误解ROLLBACK将如何工作,或者是否还有其他风险,我需要担心这种风格。

感谢您的意见。

2 个答案:

答案 0 :(得分:3)

在你给出的例子中没有问题。

第一个事务将具有独占锁,这意味着第二个事务在第一个事务提交或回滚之前不能修改该行。它必须等待(阻止),直到锁被释放。

如果你有多个语句,它会变得有点复杂。您应该阅读不同的隔离级别以及它们如何允许或防止“丢失更新”等现象。

答案 1 :(得分:1)

回滚是事务的一部分,并且在回滚期间将保持锁定。 ACID中的* A * tomic。 在释放所有锁之前,用户B才会启动。

会发生什么:

  • 用户A锁定行
  • 用户B在释放锁之前不会看到行
  • 用户A回滚,释放锁定,从未发生过更改。
  • 用户B看到行。 -1000将导致9000

但是,如果用户B已经阅读了余额,那么在UPDATE方面我就不一致了。这取决于你实际在做什么以及以什么顺序进行,因此需要理解isolation levels(以及幻像和非可重复读取的问题)

SERIALIZABLE或REPEATABLE READ的替代方法可以在事务模式下使用sp_getapplock来对信号的部分信号进行处理。