什么是不可重复读和幻读之间的区别?
我已阅读维基百科隔离(数据库系统)的文章 ,但我有几个疑问。 在下面的例子中,将发生的事情: 不可重复读和幻读 ?
事务A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
OUTPUT:
1----MIKE------29019892---------5000
事务B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
事务A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
另一个疑问是,在上述例子中,其中隔离级别应使用? 为什么?
Answer 1:
维基百科 (对于此有很大的和详细的例子):
阿非重复读时,当事务的过程中,一排被检索两次且行内的值读取之间不同。
和
时,在一个事务的过程中,两个相同的查询被执行时,会发生幻像读,和由所述第二查询返回的行的集合是从所述第一不同。
简单的例子:
- 用户A运行相同的查询两次。
- 在此期间,用户B运行的事务,并提交。
- 非重复读:该A行用户A已经查询具有不同的值的第二时间。
- 幻读:查询中的所有的行具有相同的值之前和之后, 但正在选择的不同的行 (由于B已删除或插入的一些)。 例如:
select sum(x) from table;
将返回不同的结果,即使没有受影响的行本身已被更新,如果行已添加或删除的。
在上面的例子,这隔离级别被使用?
什么隔离级别你需要取决于你的应用。 有很高的成本到“更好的”隔离电平(如减少并发)。
在你的榜样,你不会有一个幻象,因为你从一个单行(按主键标识)只选择。 你可以有不可重复的读取,因此,如果这是一个问题,你可能希望有防止隔离级别。 在Oracle中,事务A还可以发出一个SELECT FOR UPDATE,然后事务B不能,直到完成更改行。
Answer 2:
一个简单的方法,我喜欢去想它是:
这两种不可重复和幻象读取都从不同的事务,之后您的交易开始已经提交,然后由你的交易读取数据修改操作的事情。
不可重复读是当你的交易读取另一个事务提交的更新 。 同一行现在有比它当你的交易开始不同的值。
幻象读取类似,但是从提交的内页阅读和/或从另一个事务删除时。 还有,因为你开始交易已经消失新的行或列。
脏读类似于不可重复和幻读,但涉及到读未提交的数据,当一个UPDATE,INSERT,或从另一事务中删除被读取发生,以及其他事务尚未提交的数据。 它是阅读“进行中”的数据,这可能是不完整的,并且可能从来没有真正被提交。
Answer 3:
正如上文这篇文章中, 不可重复读异常如下所示:
- Alice和Bob启动两个数据库事务。
- Bob的读取后记录和标题列值为交易。
- 爱丽丝修改特定职位记录的酸价值的称号。
- 爱丽丝提交了数据库事务。
- 如果Bob的重新读取记录后,他将观察不同版本的表行。
在这篇文章中关于幻像读 ,你可以看到,这一反常现象可能发生如下:
- Alice和Bob启动两个数据库事务。
- Bob的读取所有与后一行的1标识符值相关联的post_comment记录。
- 爱丽丝增加了其与具有1的标识符值的交行相关联的新post_comment记录。
- 爱丽丝提交了数据库事务。
- 如果Bob的重新读取具有POST_ID列值等于1 post_comment记录,他将观察不同版本的结果集。
所以,虽然不可重复读适用于单排, 幻影阅读是关于一个范围的满足给定的查询过滤条件的记录。
Answer 4:
阅读现象
- 脏读 :从另一个事务读取数据UNCOMMITED
- 不可重复读 :从读取已提交的数据
UPDATE
从另一个事务查询 - 幻影读 :从读取提交数据
INSERT
或DELETE
从另一个事务查询
注意 :从另一个事务DELETE语句,也有造成在某些情况下非重复读取的概率非常低。 它发生在当DELETE语句不幸的是,除去对当前事务中查询非常同一行。 但是,这是一种罕见的情况下,与远更不可能在拥有数百万行的每个表的数据库发生。 含有交易数据表通常具有在任何生产环境高数据量。
此外,我们可以观察到,更新可能是在大多数使用情况,而不是实际的INSERT或删除更频繁的工作(在这种情况下, 非重复读取的危险仅保留- 幻象读取是不可能在这些情况下)。 这就是为什么更新从INSERT,DELETE区别对待,并将所得的异常也被命名不同。
还有与处理的INSERT,DELETE操作,而不仅仅是处理更新相关的附加处理成本。
不同的利益隔离级别
- READ_UNCOMMITTED防止无关。 这是零隔离级别
- READ_COMMITTED防止只有一个,即脏读
- REPEATABLE_READ防止两个异常:脏读和不可重复读
- SERIALIZABLE防止所有三个异常:脏读,不可重复的读取和幻象读取
那么为什么不直接设置在任何时候都SERIALIZABLE交易? 那么,答案对上述问题是:SERIALIZABLE设置使交易速度很慢 ,这是我们又不想。
事实上交易时间消耗在以下速度:
SERIALIZABLE> REPEATABLE_READ> READ_COMMITTED> READ_UNCOMMITTED
所以READ_UNCOMMITTED设置是最快的。
摘要
实际上,我们需要分析的使用情况,因此,我们优化了交易时间,还可以防止大部分的异常决定的隔离级别 。
请注意,在默认情况下数据库具有REPEATABLE_READ设置。
Answer 5:
有一个在这两种隔离级别之间实行差别。
对于“不可重复读”,则需要行锁定。
对于“幻象”,需要范围的锁,即使一个表锁。
我们可以通过实现这两个层面两阶段锁定协议。
Answer 6:
与不可重复读的系统,事务A的第二个查询的结果将反映在事务B更新 - 它会看到新的金额。
在一个系统,允许幻象读取,如果事务B分别以插入新的行与ID = 1,事务A将看到当执行第二查询的新行; 即虚读不可重复读的一个特例。
Answer 7:
接受答案表示最重要的是,两者之间所谓的区别其实并不显著可言。
如果一排“被检索两次,行内的值之间的读取差异”,那么他们是不是同一行(不正确的RDB讲同样的元组),它是那么确实是定义还有的情况是“集合由所述第二查询返回的行与所述第一不同的”。
至于“该隔离级别应使用”的问题,更多的数据是至关重要有人在什么地方,更多的将是可序列化是唯一合理的选择的情况下。
Answer 8:
我想有间非repeateable读取和幻像读一些差异。
非repeateable意味着有拖交易A和B,如果B能看到A的修改,所以可能发生脏读,所以我们让B A提交后注意到A的修改。
有新的问题:我们假设B通知书的的变形例的承诺之后,就意味着修改其B拿着,有时B就再读一行行的值,所以B将获得与第一次不同的新价值,我们得到的,我们把它叫做非repeateable,来处理这个问题,我们让在B记住一些东西(因为我不知道会怎样还记得)当B开始。
让我们来想想新的解决方案,我们可以看到有新的问题为好,因为我们假设B记住一些东西,所以发生在一个什么时,B不能受到影响,但是当B要插入一些数据表和B检查表,以确保没有记录,但是这个数据已经被插入,那么也许会出现一些错误。 我们把它叫做幻影读。
Answer 9:
非重复读是隔离级别和幻象读取(读取由其他事务提交的值)的一个概念(例如读脏读或快照读取的类型)。 不可重复读隔离级别允许幻象但不脏读或快照读取。
文章来源: What is the difference between Non-Repeatable Read and Phantom Read?