UPDATE = DELETE(标记为)+ INSERT?

时间:2010-11-27 12:02:04

标签: sql sql-server database oracle

这是SQL Server的问题,但我很欣赏其他DBMS上下文正确识别的答案。

Seth Lynch在MSDN论坛中回答我的问题:

告诉:

  

“当数据更新时,它没有被覆盖 - 原始行被标记为已删除并且插入了新行”

这是正确的陈述吗?你能在文档中提供支持这方面的参考文献吗? 怎么验证?

相关讨论:

更新:不久前我认为READ UNCOMMITTED事务隔离级别允许脏读(或者,SQL Server中的相同内容,通过WITH(NOLOCK)提示)允许读取(来自其他事务)未提交(或已提交) ,如果尚未更改)值但未部分更改(部分更新,部分删除或部分插入。

RESUME':简而言之,该短语一般而且在大多数情况下是不正确的(虽然它明确表示SQL Server中相当罕见的情况)

3 个答案:

答案 0 :(得分:9)

根据Kalen Delaney的说法,在她的书“ Inside Microsoft SQL Server 2005:存储引擎”中,SQL Server 2005(现在是2008)可以使用插入/删除或就地更新行,只需更改一列的值即可。以下是她在p上所说内容的快速摘要。这本书的第306-311页。

SQL Server 2005/2008中的正常行为是更新一行。该行保留在页面上的相同位置,仅更改受影响的字节。这方面的一个例子是更新整数列中的值,该值不是culstered索引的一部分。

当行的大小发生变化并且不再适合原始页面时,可以使用插入/删除更新行。当您更改varchar列中的值并使其更长时,可能会发生这种情况。当聚簇索引列发生更改并且行因其在索引中的位置而需要移动时也会发生这种情况(因为行按聚簇键排序)。这方面的一个例子是在姓氏上带有聚簇索引的表中将某人的姓氏从“史密斯”改为“琼斯”。

答案 1 :(得分:2)

这取决于实施。

通常,当使用多版本并发控制(MVCC)时,保留原始行。它被标记为删除它的事务删除并创建替换行,或者在事务上下文中的其他地方存储增量,直到事务提交并将增量应用于现有行。

在基于锁的并发控制中,可以就地更改行,因为只有一个事务可以读取和写入该行。

详细信息取决于实现。有些系统将使用delta直到提交,有些系统会更改行但保留原始副本以便在回滚时使用。

答案 2 :(得分:1)

在Oracle中,UPDATE始终更改原始行。该行的旧值将写入UNDO日志,并作为多版本并发控制(MVCC)实现的一部分保留一段时间。

只要未提交新值,所有其他事务都将从UNDO日志中获取旧值。如果您的查询在新值的COMMIT之前或某些事务隔离模式之前启动,则会发生相同的情况。

如果新值更大且行不再适合同一页面,则该行将迁移到新页面,并释放旧页面上的空格。