我正在努力理解读取、提交和未提交的隔离级别。我知道理论上读未提交允许脏读和读提交不允许,但我仍然不能真正理解。

考虑到上面的数字,如果没有一个事务被中止,那么最终的结果对于读提交和读未提交都是一样的吗?
发布于 2019-01-06 15:55:51
如果您使用读提交的隔离级别,T2需要在步骤4中等待T1完成并提交其工作。此外,步骤6中的T1无法找到带Maria%的Nome,因此删除0行。
但是在读未提交的隔离级别上,可以同时执行读/写操作。
结果用于读取提交的隔离级别,
Pessoas (Jaoa Silva, 96.....)
Pessoas (Maria Fon..., 9199...)
Pessoas (Joao Manuel Silva, 9699...)对于读未提交的隔离级别,则为
Pessoas (Joao Manuel Silva, 9699...)发布于 2019-01-07 10:39:06
您的示例与Isolation Levels无关。这是因为它们影响readers行为,而不是writers,在您的示例中只有writers。
您应该参考这篇BOL文章:了解隔离级别,它说
选择事务隔离级别不会影响为保护数据修改而获得的锁。事务总是对它修改和保存的任何数据获得独占锁,直到事务完成为止,而不管为该事务设置的隔离级别如何。For 读取操作,事务隔离级别主要定义保护级别,使其免受其他事务修改的影响。
在您的示例中,没有一个事务是read,它们都是modify。第一个事务将在感兴趣的RID或key (如果它是堆表或群集表)上获得RID或key(如果它是堆表或群集表) --我以后将称之为res_1 --用于插入事务,并在事务的所有时间内保存它(对应的page和object上也有IX ),第二个事务的第一个语句也是如此:当插入时,它将在E 126res_2E 227/code>上获得X。
在DELETE尝试中,第二个事务将被阻塞,因为它无法获得X (如果在where条件下没有索引),这是因为在第一个事务持有的同一资源(res_1)上已经存在X。第二个事务中没有第二个INSERT,因为以前的DELETE被阻塞了。
最后,当第一个事务尝试它的DELETE时,它需要res_2上的X或U (取决于索引的存在),但是它已经被tran2用X阻塞了,所以它也被阻塞了,并且没有退出这种情况,每个会话等待另一个会话完成,没有会话能够完成,此时发生deadlock,服务器将通过rolling back解决它--事务之一。
发布于 2019-01-06 16:07:57
读取未提交的数据允许读取其他事务未提交的脏数据。Server引擎忽略正在读取的表下的任何锁,并直接从内存读取数据。
READ将读取已经提交的数据,但如果数据受到其他事务的影响,则会等待。
因此,在提供系统的示例中,系统不仅正在读取,而且还试图删除仍未提交的行,因此,两者都将等待其他事务完成,该示例是死锁的典型示例。
为了缓和已提交与未提交之间的差异,我将向您展示一个简单而明确的示例,我们将在这两种模式下运行两次。
-- Query Window 1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- Prepare for first Run
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- Prepare for second Run
BEGIN TRANSACTION -- Step 1
INSERT INTO Audit (ProductID, PrevValue, NewValue, ChangedBy)
VALUES (1, 'AAA', 'aaa', SYSTEM_USER); -- Step 3
COMMIT TRANSACTION -- Step 5
-- Query Window 2
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- Prepare for first Run
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- Prepare for second Run
BEGIN TRANSACTION -- Step 2
SELECT * FROM Audit WHERE PrevValue = 'AAA' -- Step 4
COMMIT TRANSACTION -- Step 6我们必须先在两个查询中运行未提交级别的行,然后转到第一个,运行步骤1,转到第二个,步骤2,等等。在未提交时,当我们运行步骤4时,我们将在执行脏读取时(从内存中)立即看到结果。对于第二次运行,我们将首先使用以下方法删除行测试:
DELETE FROM Audit WHERE PrevValue LIKE 'AAA'; 然后,将在两个查询窗口中运行提交级别的行,并运行相同的序列。我们现在将观察到,当我们运行步骤4时,系统仍然没有响应。就在我们运行步骤5提交insert的那一刻,窗口将显示结果。
我希望现在的问题更清楚。
https://stackoverflow.com/questions/54063118
复制相似问题