第一步|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提交。
5条答案
按热度按时间gtlvzcf81#
你可以用这种方式模拟它。打开Microsoft SQL Management Studio。打开两个选项卡并在这两个选项卡中启动事务。
在第一个窗口中选择数据,在第二个窗口中修改,然后提交更改。
然后,重新运行先前的SELECT。数据已更改。这是不可重复的阅读现象。
6jjcrrmo2#
您可以通过SQL Server和2个命令提示符模拟不可重复读。
首先,设置**
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读为DavidStep 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提交。tmb3ates3#
当第二个事务多次访问同一行并每次读取不同的数据时,就会发生不可重复的读取。这涉及对同一行的多次读取。每次,信息都会被另一笔交易更改。
这里的重点是:
SELECT .....
读取数据,并对它读取的那些行使用共享(读取)锁-但就在它读取它们的时候(并在第一次读取它们之后立即释放锁SELECT ...
再次读取这些行时-这一次它可能会得到不同的结果。这是您在使用默认设置
READ COMMITTED
时遇到的问题-读取操作仅在读取时获取共享锁,并在读取数据后立即释放它。在那之后,其他交易可以(并且将会!)修改数据,以便再次读取相同的行可能会产生不同的结果。使用
REPEATABLE READ
,读取事务在它读取的那些行上保持一个共享(读取)锁**,直到事务结束**--从而防止其他事务在它结束之前修改数据。所以说真的-任何使用默认
READ COMMITTED
隔离级别的读操作都是不可重复的读操作。不需要模拟--这些都是真实的东西!ghhkc1vu4#
如果行被第一个事务锁定,第二个事务如何访问数据
您认为第一个事务将锁定该行的假设是错误的。它只会锁定它很短的一段时间,刚好足够读取它,然后释放锁。随后的读取将再次锁定它,因此在此期间该行可能发生任何事情。
考虑此时间序列,并查看事务T1在读取已提交隔离下如何查看同一SELECT的不同结果:
i1icjdpr5#
在SSMS中打开2个查询窗口
第一个查询:
第二
创建和填充表
运行第一个查询,然后运行第二个查询,然后从第一个查询运行
select
语句您将第一次看到
1
,第二次看到2