事物的四种隔离级别

事务的四种隔离级别

我们将以如下伪SQL代码为例,说明事务的四种隔离级别。

-- 事务1
begin;

insert into table1 (val);

update table2
set a = a + 1
where id = 1;

commit;

-- 事务2
begin;

select count(*)
from table1;

select a 
from table2
where id = 1;

-- 标志点 --

select count(*)
from table1;

select a
from table2
where id = 1;

commit;

可串行化

是最高级别的隔离,两个并发的事务的调度与某种串行化调度一致,100%隔离,不会造成冲突。因此事务2的前后两次查询结果是相同的。但因为隔离级别过高,导致并发程度很低,在现实中很少使用。

可重复读

是MySQL的默认模式。如果一个事务已提交,它添加了新数据,那么这些数据对其他正在执行的事务是可见的;但它是修改了某一数据,那修改的结果对其他事务是不可见的。即对于已提交的事务,不隔离新增数据,但隔离已存在(修改后)的数据。

以上述代码为例,若在事务2的标志点处,事务1已提交,那么事务2前后两次查询的count(*)结果是不一样的,这就是”幻读“,因为新增的数据对事务2是可见的;但事务2前后两次查询的a的值是一样的,因为已存在但修改后的数据对它是不可见的,是可重复读的。

已提交读

是SQL Server的默认模式。对于已提交的事务,既不隔离新增的数据,也不隔离已存在的数据,也就是可重复读的基础上突破了已存在数据的隔离。

因为对刚提交的值都可见,因此若在事务2的标志点处,事务1已提交,count(*)a的值在前后两次的查询中都不一样。

未提交读

是最低级别的隔离,前几个隔离级别都会隔离其他正在执行的事务,而未提交读,会对最新版本的值(可以是未提交的)可见。

若在事务2的标志点处,事务1已执行完毕,但还未提交,事务2的count(*)a的值在前后两次的查询中还是会不一样。此时若事务1回滚,那么事务2在第二次读取的值就没有意义,这就是”“脏读”


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!