我认为上述隔离级别非常相似。有人可以用一些很好的例子来描述主要区别是什么?
答案 0 :(得分:483)
Read committed是一个隔离级别,可以保证读取的任何数据读取已提交。它只是限制读者看到任何中间的,未提交的,“脏”的读。 IT不承诺,如果事务重新发出读取,将找到相同数据,数据在读取后可以自由更改。
可重复读取是一个更高的隔离级别,除了保证读取提交级别之外,它还保证读取的任何数据都不能更改,如果事务再次读取相同的数据,它将找到先前读取的数据,保持不变并可供阅读。
下一个可序列化的隔离级别提供了更强大的保证:除了所有可重复读取保证之外,它还可以保证没有新数据可以被看到随后阅读。
假设你有一个表T,其中C列有一行,比如它的值为'1'。并且考虑一下如下的简单任务:
BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;
这是一个简单的任务,从表T发出两个读取,它们之间有1分钟的延迟。
如果您遵循上述逻辑,您可以快速意识到SERIALIZABLE事务虽然可以让您轻松生活,但始终完全阻止每个可能的并发操作,因为它们要求任何人都无法修改,删除也不插入任何行。 .Net System.Transactions
范围的默认事务隔离级别是可序列化的,这通常可以解释导致的糟糕性能。
最后,还有SNAPSHOT隔离级别。 SNAPSHOT隔离级别与可序列化具有相同的保证,但不要求并发事务不能修改数据。相反,它迫使每个读者看到它自己的世界版本(它自己的'快照')。这使得它非常容易编程以及非常可扩展,因为它不会阻止并发更新。但是,这种好处需要付出代价:额外的服务器资源消耗。
补充读物:
答案 1 :(得分:59)
从事务开始就维护数据库的状态。如果在session1中检索值,然后在session2中更新该值,则在session1中再次检索它将返回相同的结果。读取是可重复的。
session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron
在事务的上下文中,您将始终检索最近提交的值。如果在session1中检索值,在session2中更新它,然后在session1again中检索它,您将获得在session2中修改的值。它读取最后提交的行。
session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;
session1> SELECT firstname FROM names WHERE id = 7;
Bob
有道理吗?
答案 2 :(得分:19)
根据我对这个帖子和@ remus-rusanu答案的阅读和理解,答案就是基于这个简单的场景:
有两个流程A和B. 过程B正在阅读表X. 流程A写在表X中 进程B再次阅读表X.
答案 3 :(得分:12)
旧问题已经有了一个已接受的答案,但我想考虑这两个隔离级别是如何改变SQL Server中的锁定行为的。对于那些像我一样调试死锁的人来说,这可能会有所帮助。
READ COMMITTED(默认)
在SELECT中获取共享锁,然后在SELECT语句完成时释放 。这就是系统如何保证不存在未提交数据的脏读。在SELECT完成之后和事务完成之前,其他事务仍然可以更改基础行。
重复阅读
共享锁在SELECT中获取,然后仅在事务完成后才释放 。这就是系统如何保证您读取的值在事务期间不会更改(因为它们在事务完成之前一直处于锁定状态)。
答案 4 :(得分:10)
答案 5 :(得分:0)
我认为这张图片也很有用,当我想快速记住隔离级别之间的差异时(感谢youtube上的kudvenkat),它可以作为参考
答案 6 :(得分:0)
请注意,可重复读取的可重复是针对元组,而不是整个表。在ANSC隔离级别中,可能会发生 phantom read 异常,这意味着两次读取具有相同where子句的表可能会返回不同的结果,并返回不同的结果集。从字面上看,它不是可重复的。
答案 7 :(得分:-1)
我对最初接受的解决方案的观察。
在RR(默认mysql)下 - 如果tx已打开并且已触发SELECT,则另一个tx无法删除属于先前READ结果集的任何行,直到之前的tx被提交(事实上,新tx中的delete语句将只是挂起,但是下一个tx可以毫无困难地从表中删除所有行。顺便说一下,在之前的tx中的下一个READ仍会看到旧数据,直到它被提交。