如何在sql server中模拟不可重复的读取

时间:2013-04-10 20:36:36

标签: sql-server transactions deadlock

我在msdn上阅读了以下代码行,但我对此并不清楚,并希望模拟。

  

当第二个事务访问时,会发生不可重复的读取   每次排几次并每次读取不同的数据。这涉及到   多行读取同一行。每次,信息都会改变   另一笔交易。

如果第一个事务在读提交的隔离级别下锁定了行,我不明白第二个事务如何访问数据。

4 个答案:

答案 0 :(得分:3)

您可以通过这种方式模拟它。打开Microsoft SQL Management Studio。打开2个标签并在两个标签中开始交易。

在第一个窗口中选择数据并在第二个窗口中修改它并提交更改。

然后,重新运行上一个选择。数据已更改。 这是不可重复的读取现象

enter image description here

答案 1 :(得分:0)

  

当第二个事务多次访问同一行并每次读取不同的数据时,会发生不可重复的读取。这涉及同一行的多次读取。每次,信息都会被另一笔交易更改。

这一点是:

  • 事务A使用SELECT .....读取数据并对其读取的行进行共享(读取)锁定 - 但只是在读取它们时(并且立即释放锁定首先阅读后

  • 事务B现在可以修改其中一些行

  • 当事务A返回并使用SELECT ...再次读取这些行时 - 这次可能会得到不同的结果。

这是使用默认设置时遇到的问题 - READ COMMITTED - 只有在读取时,读取操作才会获取共享锁,并在读取数据后立即将其释放。之后,其他事务可以(并将!)修改数据,因此再次读取相同的行可能会产生不同的结果。

使用REPEATABLE READ,阅读交易会在的行上保持共享(读取)锁定,直到交易结束 - 从而阻止其他交易在数据结束之前修改数据。

实际上 - 使用默认READ COMMITTED隔离级别的任何读取操作都是不可重复的读取。无需模拟 - 这些都是真实的东西!

答案 2 :(得分:0)

在SSMS中打开2个查询窗口

首先查询:

set transaction isolation level read committed
begin transaction
select * from _tmp

第二

update _tmp set id = 2

创建并填充表

create table _tmp ( id int)
insert _tmp (id )values(1)

运行第一个查询,然后运行第二个,然后从第一个查询

运行select语句

您将第一次看到1,第二次看到2

答案 3 :(得分:0)

  

如果第一个事务锁定了行,第二个事务如何访问数据

假设第一个事务会锁定行,你错了。它只会锁定它很短的时间,只需要读取它,然后释放锁定。后续读取将再次锁定 ,因此在此期间任何行都可能发生。

考虑这个时间序列,看看在read committed isolation下的事务T1如何看到相同SELECT的不同结果:

T1: begin transaction
T1: select * from table <-- returns row 1 and row 2
T2: begin; insert into table row 3; commit;
T1: select * from table <-- returns row 1, row 2 and row 3
T3: begin; delete row 2 from table ; commit;
T1: select * from table <-- returns row and row3