MySQL之MVCC、索引
数据并发控制
LBCC
对于修改操作都为其加上排他锁,想要读取一个数据得等上一个事务提交才能去访问,这样并发性很低,所以就有了MVCC
MVCC
首先理解MVCC要先理解事务的四种隔离级别,对于以下四种级别,MVCC主要是解决RC和RR的问题,对于RU和Serializeable这两种,要么直接读取最新的,要么直接加上悲观锁就可以实现,不需要MVCC。
RU 读未提交/脏读
RC 读已提交/不可重复读
RR 可重复读/幻读
Serializeable 串行
首先在MVCC中有两个很重要的组件,undo表和Read_View,undo来记录在每一行都有两个隐藏列,一个是事务id和回滚指针,在一次事务操作时,会在undo表中进行记录,而进行一次Select操作时,会生成一个Read_View,这个Read_View会根据undo生成一个列表,这个列表记录了目前活跃的事务id,如果Read_View当前的事务id小于这个列表最小的id,说明该事务已经被提交是可以安全访问的,而如果在这之间,如果这个id存在于列表中则说明事务还未提交,则需要等待事务提交之后再执行,如果不在则说明事务已经被提交,可以执行查询,而如果是大于列表中最大的事务id,则说明事务还是Read_View之后生成的,不可以被访问。
那么解决RC和RR有什么区别的呢?在RC中,每一次的读取数据都要去重新生成一个Read_View,而在RR中则是使用第一次读取得到的Read_View。
MySQL索引
首先MySQL的InnoDB和MyISAM都是使用的B+tree,只不过InnoDB索引是跟数据文件绑定在一起,而MyISAM是单独的索引文件,且文件是可以被压缩的。
由于B+tree的特性,所有数据都在叶节点上,对于数据库来说B+tree比B-tree更有优势,在叶节点上是有链表的,查询会更加的方便。
每一个页节点占16KB,这样设计的原因在于操作系统在读取数据的时候并不是需要多少就读多少,而是把目标数据周围的4KB数据读进内存,这样设计页节点能够使得数据库的读效率更高。
在InnoDB里面,索引分为聚集索引和非聚集索引,在每个表里面必须有一个聚集索引,如果没有手动指定则是第一个为notnull的列,如果都没有,则会有一个隐藏列来代替。聚集索引是包含了一整行的数据,所以我们通常指定一个主键,然后通过这个主键来查询数据,这样效率会更高,不会涉及到回表操作;非聚集索引里面存的是索引指定的列和主键,在我们查询的时候会造成回表聚集索引来查询所需要的数据,那么如何去防止这种回表操作呢,就是用覆盖索引,即查询的时候只去查询非聚集索引指定的列,然后通过连表操作,根据主键去取出对应的数据。在MyISAM里面,非聚集索引不是包含的主键id,而是指向的数据块。