首先回顾一下并发事物问题:
- 脏读:A事物中读到了B事物未被提交的数据
- 不可重复读:A事物两次读的过程中,B事物修改了该行数据并提交,导致同一事物两次读的结果不一样
- 幻读:A事物两次读的过程中,B事物新增了一行数据并提交,导致同一事物两次读的记录数不一样
幻读可以看作不可重复读的一种特殊情况,在解决方式上,由于记录锁只能锁住已存在的记录,为了避免插入新纪录,需要依赖间隙锁
InnoDB下的事物隔离级别分为四种,是基于锁和MVCC共同实现的:
- 读未提交:
- 问题:脏读,不可重复读,幻读
- 实现:
- 读:读的时候不会涉及到版本链
- 写:
- 读已提交:
- 问题:不可重复读,幻读
- 实现:
- 读:基于语句级别的readView,每次select都会生成一个快照读
- 写:没有间隙锁!
- 有索引:行锁
- 没有索引:表锁
- 可重复读(默认):
- 问题:幻读
- 实现:
- 读:基于事物级别的readView
- 写:
- 有索引:
- 索引命中:行锁
- 索引未命中:间隙锁
- 没有索引:表锁
- 有索引:
- 串行化
- 所有事物直接串行执行