我正在阅读快照隔离优势。快照隔离级别可防止脏读,不可重复读和幻像读。但是在我下面提到的测试中,我可以看到幻影读取正在发生。所以我的问题是快照隔离如何防止幻像读取?
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的测试值,这是不允许的。
答案 0 :(得分:1)
幻像读取被定义为在同一事务中发出相同的查询并获得不同的结果。在您的情况下,您从未在会话1中发出第二个查询,因此,根据定义,您没有经历幻像读取。
但即使你这样做,也不会阻止会话2中的插入。快照隔离(以及密切相关的读提交快照)通过不必锁定提供隔离级别建议的保证所需的数据来增加并发性。这是以维护版本存储为代价的。引用the docs:
SNAPSHOT隔离指定在事务中读取的数据永远不会反映其他同时事务所做的更改。事务使用事务开始时存在的数据行版本。读取数据时,不会对数据进行锁定,因此SNAPSHOT事务不会阻止其他事务写入数据。写入数据的事务不会阻止快照事务从读取数据。您需要通过设置ALLOW_SNAPSHOT_ISOLATION数据库选项来启用快照隔离,以便使用它。
现在,如果您正在尝试阻止会话2中的插入发生,您可以为会话1实现可序列化的隔离级别。但是我真的有必要在执行此操作之前这样做,因为它会发生以并发为代价。