这是SQL Server的问题,但我很欣赏正确识别的其他DBMS上下文的答案。
Seth Lynch在MSDN论坛中对我的问题的回答:
讲述:
“当数据更新时,它没有被覆盖 - 原始行被标记为已删除并且插入了新行”
这是正确的陈述吗?你能在文档中提供支持这方面的参考吗?
怎么验证?
相关讨论:
更新:不久前我认为READ UNCOMMITTED事务隔离级别允许脏读(或者,SQL Server中的相同内容,通过WITH(NOLOCK)提示)允许读取(来自其他事务)未提交(或者已提交,如果没有)但已经改变了)但没有部分改变(部分更新,部分删除或部分插入)。
简称':简而言之,该短语通常是大多数情况下不正确的(虽然它明确表示SQL Server中相当罕见的情况)
据卡伦德莱尼在她的书中说 Microsoft SQL Server 2005内部:存储引擎,SQL Server 2005(现在是2008)可以通过使用插入/删除或就地更新行,只需更改一列的值即可。以下是她在p上所说内容的快速摘要。这本书的第306-311页。
SQL Server 2005/2008中的正常行为是更新一行。该行保留在页面上的相同位置,仅更改受影响的字节。一个例子是更新整数列中的值,该值不是culstered索引的一部分。
当行的大小发生变化并且不再适合原始页面时,可以使用插入/删除更新行。当您更改varchar列中的值并使其更长时,可能会发生这种情况。当聚簇索引列发生更改并且由于其在索引中的位置而需要移动行时也会发生这种情况(因为行是按聚簇键排序的)。这方面的一个例子是在姓氏上带有聚簇索引的表中将某人的姓氏从“史密斯”改为“琼斯”。
这取决于实施。
通常,当使用多版本货币控制(MVCC)时,保留原始行。它被标记为删除它的事务删除并创建替换行,或者将delta存储在事务上下文的其他位置,直到事务提交并将delta应用于现有行。
在基于锁的并发控制中,该行可以在原位更改,因为只有一个事务可以读取和写入该行。
细节依赖于实现。有些系统将使用delta直到提交,有些系统会更改行但保留原始副本以便在回滚时使用。
在Oracle中,UPDATE始终更改原始行。该行的旧值将写入UNDO日志,并作为多版本并发控制(MVCC)实现的一部分保留一段时间。
只要未提交新值,所有其他事务都将从UNDO日志中获取旧值。如果您的查询在新值的COMMIT之前或某些事务隔离模式之前启动,则会发生相同的情况。
如果新值更大且行不再适合同一页面,则该行将迁移到新页面,并释放旧页面上的空间。