SQL读取可以返回陈旧数据吗?

时间:2018-02-17 21:56:04

标签: sql database transactions distributed-system distributed-transactions

考虑以下SQL事务序列:

// @TransactionOne
BEGIN TRANSACTION;
CREATE TABLE T (C INT, D INT);
INSERT INTO T VALUES (1, 2);
COMMIT;

// @TransactionTwo
BEGIN TRANSACTION;
INSERT INTO T VALUES (3, 4);
COMMIT;

// @Query
SELECT COUNT(*) from T where T.C = 3;

天真的期望是@Query将返回1.但是,当我读到ACID时,我不明白数据库无法将操作序列重新排序为:[@ TransactionOne,@ Query,@ TransactionTwo]在这种情况下,它将返回0。

SQL标准是否允许这样做?典型的数据库引擎能为这种情况提供什么保证?

我也在想一个带有某种只读副本的高吞吐量OLTP引擎。根据只读副本的一致性模型,副本可能略微落后。这似乎是这种情况可能以合理的概率发生的情况。

如果确实允许这样做,那么在这里交易哪个ACID属性?

1 个答案:

答案 0 :(得分:1)

SQL没有执行顺序。它是一种声明性语言。优化器可以自由选择任何合适的顺序来产生最佳执行时间。给定SQL查询,任何人都不可能知道执行顺序。如果您添加有关所涉及的模式的详细信息(确切的表和索引定义)和估计的基数(数据的大小和键的选择性),那么可以猜测可能的执行顺序。

但是,您可以使用SQL Server中的服务器实用程序语句之类的内容,例如“Go”语句。 'Go'语句将查询分解为单独发送以进行处理的批次。在SQL Server中运行的以下代码将始终在查询计数之前完成插入事务,从而产生1。

// @TransactionOne
BEGIN TRANSACTION;
CREATE TABLE T (C INT, D INT);
INSERT INTO T VALUES (1, 2);
COMMIT;

// @TransactionTwo
BEGIN TRANSACTION;
INSERT INTO T VALUES (3, 4);
COMMIT;
GO

// @Query
SELECT COUNT(*) from T where T.C = 3;