如果两个事务都没有回滚,则读取已提交与未提交读取

use*_*264 3 sql-server read-uncommitted isolation-level read-committed

我试图了解已提交读和未提交读隔离级别。我知道理论上读未提交允许脏读而提交读不允许,但我仍然无法真正理解。

这个例子

考虑上图,如果没有任何事务被中止,那么对于已提交读和未提交读的最终结果是否相同?

sep*_*pic 5

你的例子与Isolation Levels. 这是因为它们影响readers行为,而不是writers,并且在您的示例中只有writers.

您应该参考这篇 BOL 文章:了解隔离级别 ,它说

选择事务隔离级别不会影响为保护数据修改而获取的锁。无论为该事务设置的隔离级别如何,事务始终对其修改的任何数据获得排他锁并保持该锁直到事务完成。对于 读操作事务隔离级别主要定义了免受其他事务所做修改影响的保护级别

在您的示例中,没有交易read,它们都是modify。第一个事务将获取X感兴趣的RIDkey(取决于表结构,如果它是堆表或聚簇表)——我将来会称它为res_1——用于插入并在事务的整个持续时间内保持它(它将也有IX对应的pageand object),第二个事务的第一条语句也是一样:插入时会Xres_2 上获取。

DELETE尝试时,第二个事务将被阻止,因为它无法获得X(或者U在没有索引的where情况下),这是因为第一个事务已持有X相同的资源(res_1)。并且第二INSERT个交易中不会有第二个,因为前一个DELETE被阻止了。

最后,当第一个事务尝试它时DELETE,它需要XU(取决于索引存在) on res_2,但是它已经被Xtran2阻塞了,所以它也被阻塞并且没有退出这种情况,每个会话都等待另一个会话完成并且没有会话可以完成,此时deadlock发生并且服务器将通过rolling back事务之一解决它。


Der*_*ğlu -1

如果您使用已提交读隔离级别,T2 需要在步骤 4 上等待 T1 完成并提交其工作。此外,步骤 6 中的 T1 无法找到具有 Maria% 的 Nome,因此删除 0 行。

但在读未提交隔离级别上,读/写操作可以同时完成。

结果 对于已提交读隔离级别,

Pessoas (Jaoa Silva, 96.....)
Pessoas (Maria Fon..., 9199...)
Pessoas (Joao Manuel Silva, 9699...)
Run Code Online (Sandbox Code Playgroud)

而对于读取未提交的隔离级别

Pessoas (Joao Manuel Silva, 9699...)
Run Code Online (Sandbox Code Playgroud)