1.隔离级别:
读未提交:脏读(读取其它事务未提交的数据),不可重复读,幻读
读已提交:不可重复读(一个事务的两次读取数据出现不同的结果,主要是修改操作),幻读
可重复读:幻读(一个事务的两次读取数据出现不同的结果,主要是添加和删除操作)
可序列化:串行操作,每个读取的数据行加上共享锁
2.MVCC:
当前读:基于悲观锁的实现,读到的是最新版本的数据,且会对数据上锁
快照读:基于MVCC的实现,不会对读取的内容上锁,提高并发性能,可能会读到数据的旧版本
MVCC模型:为了实现读-写冲突不加锁,这个读就是指快照读,具体实现通过3个隐式字段,undo日志,Read View等去完成。但不能解决写-写的更新丢失问题,写-写冲突需要悲观锁或乐观锁去解决。
MVCC实现原理:
1.隐式字段:DB_TRX_ID(最近修改的事务ID), DB_ROLL_PTR(回滚指针,指向这条记录的上一个版本), DB_ROW_ID(隐含的自增ID,如果数据表没有主键,InnoDB会自动以该ID产生一个聚簇索引)
实际上还有一个删除flag隐藏字段,当更新或删除时不是真的删除,而是删除flag变了
2.undo日志:
主要分为两种:insert undo log,update undo log
insert undo log代表事务在insert新纪录时产生的undo log,只在事务回滚时需要,并在事务提交后可以被立即丢弃(问题:RR级别的MVCC为什么解决不了幻读 推测:Read View是针对被读取数据产生的,第二次的快照读发现新插入的数据没有产生过Read View,所以针对它产生新的Read View判断其可见性)
update undo log事务在进行update或delete时产生的undo log,不仅在事务回滚时需要,在快照读时也需要,只有在快照读或事务回滚不涉及该日志时,才会被purge线程清除
purge:purge线程自己维护了一个read view(相当于系统中最老活跃事务的read view),如果某个记录的delete_bit为true并且DB_TRX_ID相对于purge线程的read view可见,那么这条记录可以被安全删除
对MVCC实质上有帮助的是update undo log,undo log实际上就是旧记录链表,链首是最新的旧纪录
3.Read View:
事务进行快照读操作时为读取数据生成的读视图,记录并维护系统当前的活跃事务ID,把它比作条件判断当前事务能看到哪个版本的数据。
4.判断流程:
Read View可以简单的理解成有三个全局属性,trx_list(Read View生成时刻,系统内活跃事务的id), up_limit_id(trx_list列表中最小的事务ID), low_limit_id(Read View生成时刻,系统尚未分配的下一个事务ID,也就是已出现过的事务ID的最大值+1)
当进行快照读生成Read View后,判断1)首先会比较被读取数据的DB_TRX_ID和up_limit_id,如果小于,则判断为可见,反之进入下一个判断,判断2)比较DB_TRX_ID和low_limit_id,如果大于,则判断为不可见,反之进入下一个判断,判断3)判断DB_TRX_ID是否存在于trx_list中,如果在,代表Read View生成时刻,这个事务仍在活跃,还未提交,则不可见,反之可见。
5.RC和RR级别下InnoDB快照读的区别:
RR级别下对某条记录的前后两次快照读使用的都是第一次快照读的Read View,RC级别下每一个快照读都会生成新的Read View