InnoDB中事务隔离级别和锁的关系 思路?个人理解?

1
数据库遵循两段锁协议,加锁阶段和解锁阶段,在对任何数据进行读操作之前要申请并获得S锁,在写操作之前要申请并获得X锁


2
事务中的加锁方式,事务的四种隔离级别,未提交读,已提交读(RC),可重复读(RR),可串行化,各种隔离级别对应的脏读,不可重复读和幻读


3
锁的种类:行锁 表锁
重点讲行锁,由于行锁只锁住有限的数据,对于其它数据不加限制,所以并发能力强,MySQL一般都是用行锁来处理并发事务


4
在RC(不可重读)级别中,数据的读取都是不加锁的,但是数据的写入、修改和删除是需要加锁的,在有索引的情况下mysql会过滤掉不符合条件的行,给符合条件的行加锁,如果没有索引的增删改理论上则会锁住全表,实际操作上mysql做了一些改进,在过滤条件不满足后,会调用unlock row方法,把不满足条件的记录释放锁,保证了最后只会持有满足条件记录上的锁,但是每条记录的加锁操作还是不能省略的


5
在RR级别中,RR是MySQL中InnoDB默认的隔离级别,可重读这个概念是一事务的多个实例在并发读取数据时,会看到同样的数据行,如何实现,第一次select一部分数据后,用悲观锁锁定这些数据,其他事务无法修改这些数据,就可以实现可重复读,但是效率低,而且锁不住insert进去的数据,会出现幻读,mysql用乐观锁mvcc(多版本并发控制)来避开这两种问题


6
MVCC 基于数据版本( Version)记录机制实现,读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。类似CAS的过程


7
MVCC在innodb中的读(快照读)安全的实现,在InnoDB中,会在每行数据后添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除),这两个值就是事务的版本号,保证了可重复读和去除了幻读(即使在InnoDB开启RR级别的情况下)


8
MVCC中并发提交数据时会出现冲突,那么冲突时如何解决呢?(其实就是解决当前读的安全问题)–>区分快照读(读取历史数据,select,不需要加锁)和当前读(读取当前版本数据,insert update delete时候的读,需要加锁)的区别–>MySQL为了减少锁处理(包括等待其它锁)的时间,提升并发能力,引入了快照读的概念,使得select不用加锁。而update、insert这些“当前读”,就使用Next-Key锁(GAP间隙锁和行锁的组合)–>RR级别中,事务A在update后加锁,事务B无法插入新数据,这样事务A在update前后读的数据保持一致,避免了幻读。这个锁,就是Gap锁–>根据索引的区间进行维护Gap锁,将第一次查询出来的结果进行一个区间的维护,区间取查询结果中的最小和最大值,在这个区间加锁,非此区间的insert照样可以插入,就避免了此区间的幻读情况,如果没有索引呢,就会全表上gap锁

猜你喜欢

转载自blog.csdn.net/weixin_36708538/article/details/81217373