MVCC:多版本并发控制技术。保存数据的历史版本。这样我们就可以通过比较版本号决定数据是否显示出来。
InnoDB中的RC和RR隔离事务是基于多版本并发控制(MVCC)实现高性能事务。一旦数据被加上排他锁,其他事务将无法加入共享锁,且处于阻塞等待状态,如果一张表有大量的请求,这样的性能将是无法支持的;MVCC对普通的 Select 不加锁,如果读取的数据正在执行Delete或Update操作,这时读取操作不会等待排它锁的释放,而是直接利用MVCC读取该行的数据快照。
事务版本号
每开启一个事务,我们都会从数据库中获得一个事务ID(也就是事务版本号),这个事务ID是自增长的,通过ID大小,我们就可以判断事务的时间顺序。
InnoDB的叶子节点存储的内容
Undo log
InnoDB将行数据快照保存在了Undo Log里。回滚指针将数据行的所有快照记录都通过链表的结构串联了起来,每个快照的记录都保存了当时的trx_id,也是那个时间点操作这个数据的事务ID。这样如果我们想要找历史快照,就可以通过遍历回滚指针的方式进行查找。
Read View
read view可以解决行的可见性。Read View是一个数组,由小到大保存了当前事务开启时所有还没有提交的事务列表,即不应该让这个事务看到的其他的事务ID列表。
当前有事务creator_trx_id想要读取某个行记录,这个行记录在叶子节点中的事务ID为trx_id,那么会出现以下几种情况:
MVCC下查询一条记录:
InnoDB中,MVCC是通过Undo Log + Read View进行数据读取,Undo Log保存了历史快照,而Read View规则帮我们判断当前版本的数据是否可见。
读已提交实现机制:
在隔离级别为读已提交(Read Commit)时,一个事务中的每一次SELECT查询都会获取一次Read View,同样的查询语句都会重新获取一次Read View,这时如果Read View不同,就可能产生不可重复读或者幻读的情况。
可重复读实现机制:
当隔离级别为可重复读的时候,事务只在第一次SELECT的时候会获取一次Read View,而后面所有的SELECT都会复用这个Read View,这样就能同一事务读取数据不一致的情况。
InnoDB三种行锁的方式:
InnoDB幻读解决机制:
InnoDB可以通过Next-Key锁+MVCC来解决幻读问题。InnoDB事务中,通过Next-Key锁住事务读取的范围,解决幻读情况。
例如:事务的读取height> 2.08 , Next-key将锁住heiht>2.08的部分,这样其他事务想要插入时就会失败,解决幻读问题。