Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 区别于;读“承诺”;及;“可重复读取”;_Sql_Sql Server_Isolation Level - Fatal编程技术网

Sql 区别于;读“承诺”;及;“可重复读取”;

Sql 区别于;读“承诺”;及;“可重复读取”;,sql,sql-server,isolation-level,Sql,Sql Server,Isolation Level,我认为上述隔离级别非常相似。有人能用一些好的例子描述一下主要的区别是什么吗 Read committed是一个隔离级别,它保证此时提交的任何数据都被读取。它只是限制读者看到任何中间的、未提交的“脏”读。它不保证如果事务重新发出读取,将发现相同的数据,数据在读取后可以自由更改 可重复读取是一个更高的隔离级别,它除了保证读取提交级别外,还保证任何数据读取都不能更改,如果事务再次读取相同的数据,它将发现以前读取的数据已就位、未更改且可读取 下一个隔离级别serializable提供了更强大的保证:除了

我认为上述隔离级别非常相似。有人能用一些好的例子描述一下主要的区别是什么吗

Read committed是一个隔离级别,它保证此时提交的任何数据都被读取。它只是限制读者看到任何中间的、未提交的“脏”读。它不保证如果事务重新发出读取,将发现相同的数据,数据在读取后可以自由更改

可重复读取是一个更高的隔离级别,它除了保证读取提交级别外,还保证任何数据读取都不能更改,如果事务再次读取相同的数据,它将发现以前读取的数据已就位、未更改且可读取

下一个隔离级别serializable提供了更强大的保证:除了所有可重复读取的保证之外,它还保证后续读取不会看到任何新的数据

假设您有一个表T,其中有一列C,其中有一行,假设它的值为“1”。并认为你有一个简单的任务如下:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;
这是一个简单的任务,从表T发出两次读取,两次读取之间的延迟为1分钟

  • 在“读取已提交”下,第二个SELECT可以返回任何数据。并发事务可以更新记录、删除记录、插入新记录。第二次选择将始终看到新数据
  • 在REPEATABLE READ(可重复读取)下,第二次选择保证至少显示第一次选择返回的行。在这一分钟内,并发事务可以添加新行,但不能删除或更改现有行
  • 在SERIALIZABLE reads下,保证第二个select可以看到与第一个完全相同的行。并发事务不能更改、删除行,也不能插入新行
如果遵循上面的逻辑,您可以很快意识到,可序列化事务虽然可以让您的生活更轻松,但总是完全阻止所有可能的并发操作,因为它们要求任何人都不能修改、删除或插入任何行。.Net
System.Transactions
范围的默认事务隔离级别是可序列化的,这通常可以解释由此产生的糟糕性能

最后,还有快照隔离级别。快照隔离级别提供了与可序列化相同的保证,但不要求任何并发事务都不能修改数据。相反,它迫使每个读者看到自己的世界版本(它自己的“快照”)。这使得编程非常容易,而且非常可伸缩,因为它不会阻止并发更新。然而,这一好处是有代价的:额外的服务器资源消耗

补充案文如下:

可重复读取 数据库的状态从事务开始时就维护。如果在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

有意义吗?

这个老问题已经有了一个公认的答案,但我喜欢考虑这两个隔离级别如何改变SQL Server中的锁定行为。这可能对那些像我一样调试死锁的人有所帮助

读取已提交(默认)

共享锁在SELECT中获取,然后在SELECT语句完成时释放。这就是系统如何保证没有未提交数据的脏读。在SELECT完成之后和事务完成之前,其他事务仍然可以更改基础行

可重复读取


共享锁在SELECT中获取,然后仅在事务完成后释放。这就是系统如何保证您读取的值在事务期间不会更改(因为它们在事务完成之前保持锁定)。

我对初始接受解决方案的观察


在RR(默认mysql)下-如果一个tx打开并且触发了SELECT,则另一个tx在提交上一个tx之前无法删除属于上一个读取结果集的任何行(实际上,新tx中的delete语句将挂起),但是下一个tx可以删除表中的所有行,而不会出现任何问题。顺便说一句,在提交之前,上一次发送中的下一次读取仍将看到旧数据。

根据我对该线程的阅读和理解,答案和@remus rusanu答案基于以下简单场景:

有两个事务处理A和B。 事务B正在读取表X 事务A正在表X中写入 事务B在表X中再次读取

  • ReadUncommitted:事务B可以从事务A读取未提交的数据,并且可以根据B的写入情况查看不同的行完全没有锁
  • ReadCommitted:事务B只能从事务A中读取已提交的数据,并且它可以根据仅提交的B写入看到不同的行我们可以称之为简单锁吗?
  • RepeatableRead:无论事务A在做什么,事务B都将读取相同的数据(行)。但是事务A可以更改其他行行级块
  • 可序列化:事务B将读取与以前相同的行,而事务A无法读取或写入表中<斯特罗