如何模拟不可重复读取(SQL Server)

bejyjqdl  于 2022-10-03  发布在  SQL Server
关注(0)|答案(5)|浏览(190)

我在MSDN上读到了以下代码行,但我不清楚这一点,我想模拟一下。
当第二个事务多次访问同一行并每次读取不同的数据时,就会发生不可重复的读取。这涉及对同一行的多次读取。每次,信息都会被另一笔交易更改。

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

gtlvzcf8

gtlvzcf81#

你可以用这种方式模拟它。打开Microsoft SQL Management Studio。打开两个选项卡并在这两个选项卡中启动事务。

在第一个窗口中选择数据,在第二个窗口中修改,然后提交更改。

然后,重新运行先前的SELECT。数据已更改。这是不可重复的阅读现象

6jjcrrmo

6jjcrrmo2#

  • 不可重复读(模糊读)**是指一个事务至少读了同一行两次,但同一行的数据在第一次和第二次读之间是不同的,因为其他事务同时(并发)更新了同一行的数据并提交。

您可以通过SQL Server2个命令提示符模拟不可重复读

首先,设置**READ COMMITTED隔离级别不可重复读取**:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

然后使用**“id”“name”创建“Person”表**,如下所示:

Id|名称

1|John
2|大卫

现在,使用MSSQL查询执行以下**步骤:

Flow|Transaction 1(T1)|Transaction 2(T2)|说明
-|-|

第一步|BEGIN TRAN;GO;||T1启动。
第二步||BEGIN TRAN;GO;|T2启动。
第三步|SELECT * FROM person WHERE id = 2;GO;2 David||t1读为David
Step 4||UPDATE person SET name = 'Tom' WHERE id = 2;GO;|t2将David更新为Tom
第五步||
COMMIT;GO;|t2提交。
Step 6|
SELECT * FROM person WHERE id = 2;GO;2 Tom||t1在T2提交后读的是Tom而不是David。#*不可重复读!!
Step 7|COMMIT;GO;||t1提交。

tmb3ates

tmb3ates3#

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

这里的重点是:

  • 事务A使用SELECT .....读取数据,并对它读取的那些行使用共享(读取)锁-但就在它读取它们的时候(并在第一次读取它们之后立即释放锁
  • 事务B现在可以修改其中的一些行
  • 当事务A返回并使用SELECT ...再次读取这些行时-这一次它可能会得到不同的结果。

这是您在使用默认设置READ COMMITTED时遇到的问题-读取操作仅在读取时获取共享锁,并在读取数据后立即释放它。在那之后,其他交易可以(并且将会!)修改数据,以便再次读取相同的行可能会产生不同的结果。

使用REPEATABLE READ,读取事务在它读取的那些行上保持一个共享(读取)锁**,直到事务结束**--从而防止其他事务在它结束之前修改数据。

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

ghhkc1vu

ghhkc1vu4#

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

您认为第一个事务将锁定该行的假设是错误的。它只会锁定它很短的一段时间,刚好足够读取它,然后释放锁。随后的读取将再次锁定它,因此在此期间该行可能发生任何事情。

考虑此时间序列,并查看事务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
i1icjdpr

i1icjdpr5#

在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

相关问题