快照隔离级别是不是可以防止幻读?
Posted
技术标签:
【中文标题】快照隔离级别是不是可以防止幻读?【英文标题】:does snapshot isolation level protects from Phantom read?快照隔离级别是否可以防止幻读? 【发布时间】:2015-12-27 19:34:24 【问题描述】:我正在阅读有关快照隔离优势的信息。快照隔离级别可防止脏读、不可重复读和幻读。但在我下面提到的测试中,我可以看到幻读正在发生。所以我的问题是快照隔离如何防止幻读?
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 测试值中,允许插入不应该被允许的插入值。
【问题讨论】:
【参考方案1】:幻读被定义为在同一事务中发出相同的查询并获得不同的结果。在您的情况下,您从未在会话 1 中发出第二个查询,因此根据定义,您没有遇到幻读。
但即使您这样做了,也不会阻止会话 2 中的插入。快照隔离(以及密切相关的读取提交快照)通过不必锁定提供隔离级别建议的保证所需的数据来增加并发性。这是以必须维护版本存储为代价的。引用the docs:
SNAPSHOT 隔离指定事务中读取的数据永远不会反映其他同时事务所做的更改。事务使用事务开始时存在的数据行版本。读取数据时不会对数据加锁,因此 SNAPSHOT 事务不会阻止其他事务写入数据。写入数据的事务不会阻止快照事务读取数据。您需要通过设置 ALLOW_SNAPSHOT_ISOLATION 数据库选项来启用快照隔离才能使用它。
现在,如果您试图阻止会话 2 中的插入发生,您可以为会话 1 实现可序列化隔离级别。但我真的怀疑在这样做之前是否需要这样做,因为它即将到来以并发为代价。
【讨论】:
这是一个绝妙的解释。一直以来,我一直在想 SI 会阻止 Phantom 读取...谢谢 :)以上是关于快照隔离级别是不是可以防止幻读?的主要内容,如果未能解决你的问题,请参考以下文章