我在 msdn 上阅读了以下代码行,但对此我不清楚并想进行模拟。
当第二个事务多次访问同一行并且每次读取不同的数据时,就会发生不可重复读取。这涉及对同一行的多次读取。每次,信息都会被另一笔交易更改。
如果行被第一个事务锁定在读取提交的隔离级别下,我不明白第二个事务如何访问数据。
我在 msdn 上阅读了以下代码行,但对此我不清楚并想进行模拟。
当第二个事务多次访问同一行并且每次读取不同的数据时,就会发生不可重复读取。这涉及对同一行的多次读取。每次,信息都会被另一笔交易更改。
如果行被第一个事务锁定在读取提交的隔离级别下,我不明白第二个事务如何访问数据。
你可以用这种方式模拟它。打开 Microsoft SQL 管理工作室。打开 2 个选项卡并在两个选项卡中开始交易。
在第一个窗口中选择数据并在第二个窗口中对其进行修改并提交更改。
然后,重新运行之前的选择。数据已更改。这是不可重复的读取现象。
当第二个事务多次访问同一行并且每次读取不同的数据时,就会发生不可重复读取。这涉及对同一行的多次读取。每次,信息都会被另一笔交易更改。
这里的重点是:
事务 A 使用读取数据SELECT .....
并在它读取的那些行上获取共享(读取)锁 - 但就在它读取它们时(并在第一次读取它们后立即释放锁
事务 B 现在可以修改其中一些行
当事务 A 返回并再次读取这些行时,使用SELECT ...
- 这次可能会得到不同的结果。
这是您在使用默认设置时遇到的问题- 读取操作仅在读取READ COMMITTED
时获取共享锁,并在读取数据后立即释放它。之后,其他事务可以(并且将会!)修改数据,因此再次读取相同的行可能会产生不同的结果。
使用REPEATABLE READ
,读取事务在它读取的那些行上保持共享(读取)锁,直到事务结束- 从而防止其他事务在结束之前修改数据。
真的 - 任何使用默认READ COMMITTED
隔离级别的读取操作都是不可重复读取。无需模拟 - 这些都是真实的东西!
在 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
第二次
如果行被第一个事务锁定,第二个事务如何访问数据
您假设第一个事务将锁定该行是错误的。它只会锁定它很短的时间,刚好够读它,然后释放锁。随后的读取将再次锁定它,因此在此期间该行可能发生任何事情。
考虑这个时间序列,看看事务 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