深入浅出InnoDB事务隔离

小文blog小文 2018-11-28 17:01 2506人围观

提到事务,你肯定能想到ACID,即原子性、一致性、隔离性、持久性,今天基于MySQL的InnoDB引擎聊聊事务的隔离性。

MySql的InnoDB引擎下事务的隔离分四个级别

读未提交(read uncommitted):一个事务还未提交就影响到其他事务的select读操作

读已提交(read committed):一个事务提交后才会影响其他事务的select读操作

可重复读(repeatable read):同一事务中,多次select读操作结果一致,这也是InnoDB事务的默认级别,同时,在该级别下,使用多版本控制mvcc可以避免幻读的发生

串行化(serializable):保证多个事务并发对数据的一致性没有影响,select加锁,保证串行化执行

从RU->RC->RR->SZ越来越严格,相应的效率越来越低,反之效率越高,但是就有可能出现脏读、不可重复读和幻读等问题。

首先先简单的介绍下上面几个名词

脏读:两个事务AB并行操作,事务B未提交的修改被事务A读到,称为脏读。

不可重复读:两个事务AB并行操作,事务A在某一时间点读一行数据,然后事务B修改同一行数据并提交,事务A再次读这一行数据发现与第一次不一致,称为不可重复读。

幻读:两个事务AB并行操作,事务A在某一时间点读一个范围的数据,比如 10<id<20,然后事务B新增一条ID为19的数据并提交,事务A再次读发现与第一次不一致,称为幻读。

下面根据实例,依次看看在这四种隔离级别下的效果

假设表结构   id  name,

有条数据       3  小文

mysqltrans.png

RU下:事务A在I上查询的是小文,在III上查询是xiaowen,因为可以读未提交,IV也为xiaowen,最后修改提交完是zhangsan。

RC下:事务A在I上查询的是小文,在III上查询也是小文,因为可以读已提交,IV上读的是xiaowen,因为事务B已提交,最后修改提交完是zhangsan。

RR下:事务A在I上查询的是小文,在III上查询也是小文,IV上读的还是小文,可以看到事务B提交了为什么读的还是小文呢,这是RR下可重复度的机制,再会任何一个时间节点第一次读数据的时候创建read_view,之后相同读复用这个read_view。同理RC下每次读数据都会创建read_view,所以它不能保证可重复读。最后修改提交完是zhangsan。

SZ下,事务串行执行,所以就看事务A和B谁先执行了….

锁机制

并发读取修改数据为保证数据的安全性必须要加锁。读写锁,读数据加读锁,写数据加写锁,读锁互相不排斥,读写锁和写写锁相互排斥。

锁粒度

MySQL在服务层实现了表锁,各引擎层自己实现自己的锁,比如InnoDB实现行锁,这也就是InnoDB适合高并发的互联网业务的重要因素,所以没有别的特殊要求,表引擎尽量设置为InnoDB。

锁的粒度越高,应对的并发越高,消耗的资源也越多。锁策略就是在锁开销和数据安全之间寻找平衡。

多版本控制mvcc

MySQL基于性能的考虑,不会简单的依赖行锁等,而是自己实现MVCC多版本控制,其他数据库也基本一样,只是各自实现原理不一样。具体细节不讨论了,InnoDB下除了SZ之外的其他三个隔离级别下,都是非阻塞的快照读,这也是InnoDB读性能高的重要原因。


转载请注明来自小文blog,本文标题:深入浅出InnoDB事务隔离

发布评论
生活是一场戏,主角当累了,你亦可成为观众,停下脚步,歇一歇