【问题标题】:Users updating same row at the same time SQL Server用户同时更新同一行 SQL Server
【发布时间】:2018-12-11 19:37:34
【问题描述】:

我想创建一个包含 DepartmentMaximum Capacity 列的 SQL Server 表(在这种情况下假设为 10)。当用户将自己添加到部门时,系统将检查部门中当前的分配计数(假设为 9)并将其与最大值进行比较。如果低于最大值,它们将被添加。

问题是这样的:如果两个用户同时提交,当代码检索到当前分配计数时,这两个用户都将是 9。一个用户更新该行的速度更快,所以现在它是 10,但另一个用户已经在更新 (9) 之前检索了以前的值,因此在比较时两者都是有效的,我们最终在部门中有 11 个用户。

这甚至可能吗?如何解决?

【问题讨论】:

  • 您是否考虑过设置约束以阻止该值大于 10?考虑到当UPDATE 运行时会有一个锁,第二个UPDATE 将不得不等待另一个完成。然后,第二个UPDATE 将由于约束而失败。
  • 有两种基本方法。 1) Larnu 指出,您可以创建数据库约束,但这不是一个非常动态的选项,并且仍然可能存在并发问题。 2)可以锁定表直到事务完成;如果需要,这可能是我会走的路。看看这个:stackoverflow.com/questions/25273157/…
  • 您的意思是在执行第一次更新时检查值是否已达到 10,如果已达到,则向该部门添加锁,以便将来的更新无法执行更新?
  • 不要设置=10,使用+=1
  • @DaleBurrell 我做到了,但这不是一个简单的并发,可以通过乐观或悲观并发来解决,因为我检查另一列并且软件正在动态存储值。总之谢谢

标签: sql sql-server tsql concurrency


【解决方案1】:

您的问题的答案在于了解“数据库并发”,然后为您的特定场景选择正确的解决方案。

主题太大,无法在一个 SO 答案中涵盖,因此我建议您阅读一些内容并提出具体问题。

但是,在简单的形式中,您要么阻止分配给第一个尝试获取它们的人(悲观锁定),要么在有人尝试分配超出限制后抛出错误(乐观锁定)。

在悲观的情况下,如果用户未能完成交易,您需要通过一些方法来解锁它们,例如超时。有点像订票网站上说的“这些票将在接下来的 10 分钟内为您保留,您必须在该时间内完成预订,否则您可能会丢失它们”。

当你进入最后几个位置时,你会在第一个位置之后把每个人都赶走......如果你需要这种级别的锁定,别无他法。 (那么您可以创建一个等候名单,但这本身就是另一个问题)。

【讨论】:

    猜你喜欢
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    相关资源
    最近更新 更多