innodb如何实现事务隔离级别

这篇文章主要介绍了innodb如何实现事务隔离级别,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

前言

之前的文章mysql锁机制详解中我们详细讲解了innodb的锁机制,锁机制是用来保证在并发情况下数据的准确性,而要保证数据准确通常需要事务的支持,而mysql存储引擎innodb是通过锁机制来巧妙地实现事务的隔离特性中的4种隔离级别。

事务ACID特性,其中I代表隔离性(Isolation)。隔离性是指,多个用户的并发事务访问同一个数据库时,一个用户的事务不应该被其他用户的事务干扰,多个并发事务之间要相互隔离。

我们都知道事务的几种性质,数据库中的一致性和隔离性等是实现事务的基本思想,在系统有大量的并发访问的情况下,了解和熟练应用数据库的本身的事务隔离级别,对于写出健壮性,并发处理能力强的代码还是起关键的作用。

1. 事务之间如何互相干扰

一个事务是如何干扰其他事务呢?举个例子,有如下表:

create table lock_example(id smallint(10),name varchar(20),primary key id)engine=innodb;

表中有如下数据:

1, zhangsan
2, lisi
3, wangwu

demo1:

事务A,先执行,处于未提交的状态:

insert into t values(4, 'zhaoliu');

事务B,后执行,也未提交:

select * from t;

如果事务B能够读取到(4, zhaoliu)这条记录,说明事务A就对事务B产生了影响,这种影响叫做“读脏”,即读到了未提交事务操作的记录。

demo2:

事务A,先执行:

select * from t where id=1;

结果集为

1,zhangsan

事务B,后执行,并且提交:

update t set name=xxx where id=1; commit;

事务A,再次执行相同的查询:

select * from t where id=1;

结果集为:

1, xxx

这次是已提交事务B对事务A产生的影响,这种影响叫做“不可重复读”,即一个事务内相同的查询,却得到了不同的结果。

demo3:

事务A,先执行:

select * from t where id>3;

结果集为:

NULL

事务B,后执行,并且提交:

insert into t values(4, zhaoliu); commit;

事务A,首次查询了id>3的结果为NULL,于是想插入一条为4的记录:

insert into t values(4, xxoo);

结果集为:

Error : duplicate key!

你可能会想。。。你TM在逗我?查了id>3为空集,insert id=4时又告诉我PK冲突?→_→

这次是已提交事务B对事务A产生的影响,这种影响叫做“幻读”。

如上,并发的事务可能导致其他事务出现读脏、不可重复读、幻读。为了避免如上情况出现,innodb又做了哪些努力呢?

2. InnoDB实现了哪几种事务的隔离级别?

InnoDB实现了四种不同事务的隔离级别:

读未提交(Read Uncommitted)

读提交(Read Committed, RC)

可重复读(Repeated Read, RR)

串行化(Serializable)

不同事务的隔离级别,实际上是一致性与并发性的一个权衡与折衷。

3. 四种事务的隔离级别,innodb如何实现?

InnoDB使用不同的锁策略(Locking Strategy)来实现不同的隔离级别。

a. 读未提交(Read Uncommitted)

这种事务隔离级别下,select语句不加锁,也不是快照读。

SELECT statements are performed in a nonlocking fashion.

此时,可能读取到不一致的数据,即“读脏”。这是并发最高,一致性最差的隔离级别。

b. 读提交(Read Committed, RC)

普通select是快照读;

加锁的select, update, delete等语句,除了在外键约束检查(foreign-key constraint checking)以及重复键检查(duplicate-key checking)时会封锁区间,其他时刻都只使用记录锁;

间隙锁(gap lock)、临建锁(next-key lock)在该级别下失效;

此时,其他事务的插入依然可以执行,就可能导致,读取到幻影记录。该级别是最常使用的。而且如果是不上锁的select,可能产生不可重复读。

该级别下是通过快照读来防止读脏的。因为在该级别下的快照读总是能读到最新的行数据快照,当然,必须是已提交事务写入的,所以可能产生不可重复读。

c. 可重复读(Repeated Read, RR)

这是InnoDB默认的隔离级别,在RR下:

普通的select使用快照读(snapshot read),这是一种不加锁的一致性读(Consistent Nonlocking Read),底层使用MVCC来实现;

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。