【问题标题】:Is UPDATE = DELETE(marked as) + INSERT?UPDATE = DELETE(标记为)+ INSERT 吗?
【发布时间】:2011-05-16 13:07:42
【问题描述】:

这是 SQL Server 问题,但我希望得到正确识别的其他 DBMS 上下文的答案。

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

告诉:

“当数据更新时它不会被覆盖 - 原始行被标记为已删除并插入新行”

这是正确的说法吗?您能否在文档中提供支持这一点的参考资料?
如何验证?

相关讨论:

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

RESUME':简而言之,该短语通常在大多数情况下都是不正确的(虽然它明确说明了 SQL Server 中相当不常见的情况)

【问题讨论】:

  • 那会更新 AUTO_INCREMENT 字段?

标签: sql sql-server database oracle


【解决方案1】:

根据 Kalen Delaney 在她的书Inside Microsoft SQL Server 2005: The Storage Engine 中,SQL Server 2005(现在是 2008)可以通过使用插入/删除或就地更新行,只需更改一列的值。这是她在 p 上所说的内容的快速摘要。 306-311 的书。

SQL Server 2005/2008 中的正常行为是就地更新行。该行保留在页面上的相同位置,并且仅更改受影响的字节。例如,更新不属于聚集索引的整数列中的值。

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

【讨论】:

    【解决方案2】:

    这取决于实现。

    一般情况下,当使用多版本一致性控制(MVCC)时,会保留原始行。它要么被删除它的事务标记为已删除并创建替换行,要么将增量存储在事务上下文中的其他位置,直到事务提交并将增量应用于现有行。

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

    细节取决于实现。有些系统会在提交之前使用增量,有些系统会更改行但保留原始副本以备回滚时使用。

    【讨论】:

    • 您的参考资料是什么?在她对更新到位的讨论(第 309 页)中,德莱尼写道:“此外,日志将包含每个此类更新行的单个记录,除非表上有更新触发器或标记为复制。在这些情况下,更新仍在原地进行,但日志将包含一条删除记录,后跟一条插入记录。”
    • 你是在讨论甲骨文吗,Fredt?
    • 参考“数据库管理系统”第三版,Ramakrishnan,Gehrke 和“数据库系统简介”第八版,C.J. Date。恐怕我没有页面引用,正如我所说,这取决于实现,并且可以有其他实现。
    • 那对我来说很有意义。我只是在描述 SQL Server 实现,因为我认为这就是 OP 所指的。仔细观察,我发现他也打算将这个问题作为一般性问题。
    【解决方案3】:

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

    只要没有提交新值,所有其他事务都会从 UNDO 日志中获取旧值。如果您的查询在新值的 COMMIT 之前或使用某些事务隔离模式开始,也会发生同样的情况。

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

    【讨论】:

    • “在 Oracle 中,UPDATE 总是会更改原始行”,即使聚集索引的键列已更新?
    猜你喜欢
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 2013-08-29
    • 2011-01-17
    • 2012-08-06
    • 1970-01-01
    • 2012-06-19
    • 2012-11-02
    相关资源
    最近更新 更多