【问题标题】:Does a SQL UPDATE operation read data to "local memory"?SQL UPDATE 操作是否将数据读取到“本地内存”?
【发布时间】:2014-01-14 09:09:47
【问题描述】:

This answer 引用 this Technet article 解释了丢失更新的两种解释:

可以通过以下两种方式之一来解释丢失的更新。在第一种情况下,当在第一个事务提交或回滚之前,一个事务更新的数据被另一个事务覆盖时,认为发生了丢失更新。 SQL Server 2005 中不会发生这种类型的丢失更新,因为它在任何事务隔离级别下都是不允许的。

丢失更新的另一种解释是一个事务(事务#1)将数据读入其本地内存,然后另一个事务(事务#2)发生变化此数据并提交其更改。在此之后,事务#1 根据在事务#2 执行之前读入内存的内容更新相同的数据。在这种情况下,事务 #2 执行的更新可以被视为丢失更新。

所以看起来不同之处在于,在第一种情况下,整个更新发生在“本地内存”之外,而在第二种情况下,使用了“本地内存”,这会有所不同。

假设我有以下代码:

UPDATE MagicTable SET MagicColumn = MagicColumn + 10 WHERE SomeCondition

这是否涉及“本地内存”? 丢失更新的第一种解释还是第二种解释?

【问题讨论】:

  • 肯定不是第一个,因为“这种类型的丢失更新不会在 SQL Server 2005 中发生,因为它在任何事务隔离级别下都是不允许的。”
  • @MartinSmith 我认为我们对“prone”的解释可能不同:)

标签: sql sql-server database concurrency transactions


【解决方案1】:

我想它会属于第二种解释。

但是,这种类型的UPDATE 在 SQL Server 中实现的方式仍然不可能丢失更新。为更新读取的行受到U 锁的保护(当行实际更新时转换为X 锁)。

U 锁与其他U 锁(或X 锁)不兼容

因此,在所有隔离级别下,如果两个并发事务要运行此语句,那么其中一个最终将被阻塞在另一个事务的 U 锁或 X 锁后面,并且在该事务完成之前无法继续。

因此,在任何隔离级别的 SQL Server 中,这种模式都不可能发生丢失更新。

要实现丢失的更新,您需要执行类似的操作

BEGIN TRAN

DECLARE @MagicColumn INT;

/*Two concurrent transactions can both read the same pre-update value*/
SELECT @MagicColumn = MagicColumn FROM MagicTable WHERE SomeCondition

UPDATE MagicTable SET MagicColumn = @MagicColumn + 10 WHERE SomeCondition

COMMIT

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2010-11-22
    • 2017-08-08
    • 2021-10-23
    • 2018-05-28
    • 2015-05-04
    • 1970-01-01
    相关资源
    最近更新 更多