Sql 单行插入是原子的吗?例如,在一张有1M列的桌子上?

Sql 单行插入是原子的吗?例如,在一张有1M列的桌子上?,sql,atomic,Sql,Atomic,单行插入是原子的(对于外部读取器)?假设它发生在一个有1M列的表上 在执行单个INSERT语句(即“单行”类型)时,同时发生的读取操作(可能使用“read uncommitted”隔离级别)是否可能只读取某些值(列) 我对MS SQL Server的行为特别感兴趣,尽管我认为所有主要供应商的行为都类似 关于此事的官方文件链接的额外信用积分 只读取一些值 是的,那是可能发生的。DML是原子的,因为写操作被全部持久化,或者什么都不持久化,但并发读取可以以非常奇怪的方式观察部分写操作。对于多行写入,这

单行插入是原子的(对于外部读取器)?假设它发生在一个有1M列的表上

在执行单个
INSERT
语句(即“单行”类型)时,同时发生的读取操作(可能使用“read uncommitted”隔离级别)是否可能只读取某些值(列)

我对MS SQL Server的行为特别感兴趣,尽管我认为所有主要供应商的行为都类似

关于此事的官方文件链接的额外信用积分

只读取一些值

是的,那是可能发生的。DML是原子的,因为写操作被全部持久化,或者什么都不持久化,但并发读取可以以非常奇怪的方式观察部分写操作。对于多行写入,这显然是可能的,但对于读卡器来说,即使是单行写入也不是原子的

例如,您可能会发现一个非聚集索引的插入已完成,而另一个索引的插入未完成。在罕见的、人为的情况下,读者可以察觉到这一点。例如,如果你说:

select *
from T t1 with (index(1))
full outer join T t2 with (index(2)) on (someUniqueCondition)

您可以有效地得到两个索引之间的差,这两个索引可以是非零的。实现此演示不需要索引提示。

如评论中所述,SQL Server不支持一百万列。但是,您应该能够通过两列来观察问题(在适当的情况下)

当使用
READUNCOMMITTED
(或
NOLOCK
)时,答案是“是”。在文档中找到一个参考是相当困难的,但这是一个讨论它的博客

关键问题是跨多个页面的行。只要您有LOB或
varchar(max)
或类似类型的列,就会出现这种情况。如果另一个事务正在更新包含大对象值的页面,则并发的
READUNCOMMITTED
查询可能会读取部分值。如果你有多个大的物体,这也是正确的;有些可能有新值,有些可能有旧值。因此,您可以在单个记录中得到不一致的结果

我不认为存储在一个页面上的记录会发生同样的事情(至少在实践中是这样)。如果您有一个在不同时间更新不同字段的多语句事务,而不是一条语句,则可能会发生这种情况


此外,这不应该发生在隔离级别较高的情况下。实际上,
READ_UNCOMMITTED
是一种绕过一些数据库完整性检查以获得性能的方法,这需要对一些ACID属性进行必要的放松。

是的,它们是,请参阅另一个相关问题@GiuseppeR,事务意味着“如果发生错误,允许回滚”。我感兴趣的是插入操作是否可以在其生命周期的中途观察到。想象一下,在一个有一百万列的表中插入(或更新)一行。这实际上意味着1M小的写操作。我的问题是,在所有1M写操作完成之前,读卡器是否能够观察到前几次写操作。如果您还没有读过这一次,那么相关的问题是:SQL Server不允许一个表包含任何接近一百万列的内容。更新n列并不意味着n次写入操作。你可能会在这里找到答案,这是一些可怕的东西。据您所知,这是特定于SQL Server的吗?或者,在读取未提交隔离级别中读取数据的其他RDBMS会发生这种情况吗?OP希望(我也希望如此)有关于这方面的文档吗?你有关于这种行为的参考资料吗?您的示例表明,在正常使用情况下,违反了酸性物质的性质。我理解在某些提示下(例如
READUNCOMMITTED
)会发生这种情况,但索引真的不受事务隔离级别语义的约束吗?这甚至在可重复读取的情况下也是可能的。从索引1读取的数据将看不到数据。从索引2读取将等待事务提交,然后查看数据。根据定义,Serializable没有这种异常(它没有任何异常)。这种行为的参考是我的解释。如果你不同意,我很乐意听你说。