【问题标题】:What is the difference between inconsistent analysis and non-repeatable reads?不一致的分析和不可重复读取之间有什么区别?
【发布时间】:2018-10-25 11:07:16
【问题描述】:

我已经看到了很多与不一致分析和脏读以及不可重复读取与脏读的比较,但我似乎无法理解不一致(不正确)分析与不可重复读取之间的区别?

有没有更好的方法来解释这一点。

我的困惑在于,它们都是事务的多次读取部分,其中第二个(或第三个)事务进行提交的更新。

分析不正确 - 第二个事务读取的数据是由进行更改的事务提交的。不一致的分析涉及对同一行的多次读取(两次或多次),并且每次信息被另一个事务更改,因此每次产生不同的结果,因此不一致。

在哪里

不可重复读取发生在一个事务尝试访问相同数据两次并且第二个事务在第一个事务的读取尝试之间修改数据时。这可能会导致第一个事务读取相同数据的两个不同值,导致原始读取不可重复。

我无法弄清楚它们有何不同。 谢谢。

【问题讨论】:

  • 它们是同义词。在这两种情况下,事务 A 读取一行,事务 B 更改它,事务 A 再次读取它。见coursehero.com/file/p3ra5ncs/…
  • @kfinity 教科书和网站将它们列为带有单独示例的单独问题,我无法弄清楚其中的区别。
  • 差异读取为时间之一 - 因此是细微的差异。分析不正确,事务在进行中,但可以回滚。不可重复读取读取的内容多于提交第二个事务。虽然没有足够的说服力来考虑这是一个答案。
  • @Andrew 谢谢你,但我认为“飞行中的交易”未提交,是我读到的脏读物。除非我误解了你的解释。
  • @Elizabeth - 不,我同意你的观点,这是一个肮脏的阅读。这里不正确的分析有点奇怪。 - 尤其是与 Oracle 配对时。

标签: sql oracle transactions isolation-level transaction-isolation


【解决方案1】:

在我看来,以下是不一致分析的示例,但不是不可重复读取。 该示例使用银行帐户表:

CREATE TABLE ACCOUNT(
    NO NUMERIC(10) NOT NULL PRIMARY KEY,
    BALANCE NUMERIC(9,2) NOT NULL);
INSERT INTO ACCOUNT VALUES (1, 100.00);
INSERT INTO ACCOUNT VALUES (2, 200.00);

出于性能原因,银行有另一个表冗余存储所有账户余额的总和(因此,该表始终只有一行):

CREATE TABLE TOTAL(AMOUNT NUMERIC(9,2) NOT NULL);
INSERT INTO TOTAL SELECT SUM(BALANCE) FROM ACCOUNT;

假设事务 A 想要检查冗余和是否确实正确。它首先计算账户余额的总和:

START TRANSACTION; -- PostgreSQL and SQL Standard, switches autocommit off
SELECT SUM(BALANCE) FROM ACCOUNT;

现在账户 1 的所有者存入 50 美元。这是在事务 B 中完成的:

START TRANSACTION;
UPDATE ACCOUNT SET BALANCE = BALANCE + 50 WHERE NO = 1;
UPDATE TOTAL SET AMOUNT = AMOUNT + 50;
COMMIT;

最后,事务A继续读取冗余和:

SELECT AMOUNT FROM TOTAL;

它将看到增加的值,这与它计算的总和不同(可能导致误报)。

在这个例子中,事务 A 没有两次读取任何表行,因此这不可能是不可重复读取。但是,它并没有看到唯一的数据库状态——部分信息来自事务 B 更新前的旧状态,而部分信息来自更新后的新状态。

但这肯定与不可重复读取非常相关:如果 A 再次读取了 ACCOUNT 行,这将是不可重复读取。似乎阻止不可重复读取的相同内部机制也阻止了这个问题:可以将读取行保持锁定直到事务结束,或者在事务开始时对版本使用多版本并发控制。

不过,这里还有一个不错的解决方案,即在一次查询中获取所有数据。至少 Oracle 和 PostgreSQL 保证单个查询仅针对数据库的一种状态进行评估:

SELECT SUM(BALANCE) AS AMOUNT, 'SUM' AS PART FROM ACCOUNT
UNION ALL
SELECT AMOUNT, 'TOTAL' AS PART FROM TOTAL;

在具有读写的事务调度的正式模型中,这看起来也与不可重复读取非常相似:首先 A 执行 read(x),然后 B 执行 write(x),write(y),然后是 A读(y)。如果只涉及单个对象,这将是不可重复读取。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-18
    • 2013-02-20
    • 1970-01-01
    • 2021-12-17
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多