快照隔离级别是否可以防止幻读?

问题描述 投票:0回答:2

我正在阅读有关快照隔离优点的内容。快照隔离级别可防止脏读、不可重复读和幻读。但在我下面提到的测试中,我可以看到幻读发生。所以我的问题是快照隔离如何防止幻读?

create table ABC(id int, name varchar(100))

    insert into abc
    values
    (1,'a'),
    (2,'b'),
    (3,'c')


    alter database xyz
    set allow_snapshot_isolation on

-----session 1-----

set transaction isolation level snapshot
begin transaction
update abc
set name = name + '1'
where id between 1 and 3

----session 2---------

set transaction isolation level read committed
begin transaction
insert into abc
values
(2,'inserted')

commit transaction

-------session 1 --------
commit transaction

因此,在我上面的测试值中,允许插入 id = 2 的值,而这是不应该允许的。

sql-server
2个回答
4
投票

幻读被定义为在同一事务中发出相同的查询并获得不同的结果。就您而言,您从未在会话 1 中发出第二个查询,因此根据定义,您没有遇到幻读。

但即使您这样做了,会话 2 中的插入也不会被阻止。快照隔离(以及密切相关的已提交读快照)无需锁定提供隔离级别建议的保证所需的数据,从而提高并发性。这是以必须维护版本存储为代价的。 引用文档

SNAPSHOT 隔离指定事务中读取的数据永远不会反映其他同时事务所做的更改。事务使用事务开始时存在的数据行版本。读取数据时不会对数据加锁,因此 SNAPSHOT 事务不会阻止其他事务写入数据。写入数据的事务不会阻止快照事务读取数据。您需要通过设置 ALLOW_SNAPSHOT_ISOLATION 数据库选项来启用快照隔离才能使用它。

现在,如果您试图阻止会话 2 中的插入发生,您可以为会话 1 实现可序列化隔离级别。但我真的质疑在执行此操作之前是否需要这样做,因为它将在并发成本。


0
投票

根据定义,快照隔离确实可以防止幻读,对吧? 因为正如其他评论者所说,一个事务中的多重选择不会看到其他事务的新插入。 不确定这是否是严格防止幻读,因为最终需要检查冲突,有回滚事务的风险

© www.soinside.com 2019 - 2024. All rights reserved.