考虑以下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属性?
答案 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;