【问题标题】:SQL server: Can concurrent threads update same row?SQL Server:并发线程可以更新同一行吗?
【发布时间】:2013-12-06 04:48:41
【问题描述】:

我有一个包含此更新查询的存储过程:

UPDATE TOP(1) Batch_tbl
SET locked = 1
OUTPUT inserted.batchId INTO #batchId
FROM Batch_tbl 
WHERE locked = 0;

它更新locked = 0的第一行,并设置locked = 1。

如果我有多个线程,是否有可能有 2 个以上的线程更新同一行?这是假设locked一旦为1就永远不会设置回0。

如果是这样,我怎样才能使 2+ 个线程始终更新不同的行?

【问题讨论】:

  • 您有什么理由实现自己的锁表/引擎而不是使用 MSSQL 的内置事务行锁? (msdn.microsoft.com/en-us/library/aa213026%28SQL.80%29.aspx)
  • 为什么你认为两个线程可以更新同一行?如果是这样,我不相信 MS 能够销售他们的产品。
  • @Hogan 我不知道该怎么想,所以这个问题。
  • @Hogan 是的,我问这个很愚蠢。开心吗?
  • 好吧,我不是故意的——我似乎很清楚更新锁是关系数据库功能的一个基本部分,但它可能不是那么明显。

标签: sql sql-server


【解决方案1】:

。当 SQL Server 想要更新一行时,会获取一个UPDATE 锁。这与其他锁兼容,例如共享锁(用于读取),但它与另一个更新锁兼容。

因此,如果两个并发用户尝试更新同一行,其中一个将“获胜”并获得 UPDATE 锁,而另一个用户/事务将不得不等到第一次更新完成。

【讨论】:

  • 当然,第二个人将不得不等待获得 UPDATE 锁 - 但最后获得 UPDATE 锁的人最终将设置行的数据,覆盖以前的值,对吗?
  • @KyleM:如果没有检查例如ROWVERSION 列或其他列值 - 是 - 最后一个更新数据的进程“获胜”
  • 感谢您的回复。我是否正确地说,实现这些保护(如乐观版本控制)是开发人员/ORM 工具(例如 Hibernate)而不是 DBMS 的工作?还是数据库本身就提供这种类型的保护?谢谢,我希望这不是这个回复的主题。
  • 取决于您使用的 ORM。 EF 默认使用“比较所有列值”方法,例如它使用在UPDATE 语句中读取数据时存储的“旧”列值,如果该行同时发生更改,则不会更新任何内容。但是是的 - 确保这些安全防护是开发人员的工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 2011-12-02
  • 2014-07-07
  • 1970-01-01
相关资源
最近更新 更多