SQL UPDATE操作是否将数据读取到“本地内存”?

时间:2014-01-14 09:09:47

标签: sql sql-server database concurrency transactions

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

  

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

     

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

所以看起来不同的是,在第一个场景中,整个更新发生在“本地内存”之外,而在第二个场景中则使用了“本地内存”,这就产生了不同。

假设我有以下代码:

UPDATE MagicTable SET MagicColumn = MagicColumn + 10 WHERE SomeCondition

这是否涉及“本地记忆”?是否容易对丢失的更新进行第一次或第二次解释?

1 个答案:

答案 0 :(得分:3)

我想它会受到第二种解释。

但是,在SQL Server中实现此类UPDATE的方式仍然无法进行丢失更新。读取更新的行受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