1.谈谈对mysql索引的认识。
- 主键查询走索引,我们一般使用的索引都是Btree索引;
- MyISAM和InnoDB索引结构有很大差异,这里以InnoDB为例,InnoDB的叶节点存储的是数据的行,而除了主键之外的列索引存储的是主键key,也就是说在查询的时候需要二次查询,先通过列索引找到主键,再通过主键索引找到row。
- 针对我们经常查询的多列场景,我们可以建组合索引,组合索引在可以尽可能多的运用列的查询规则。说到组合索引那么必须说一下最左前缀原则:指的的是在sql where子句中一些条件或表达式中出现的列的顺序要保持和多索引的一致或以多列索引顺序出现,只要出现非顺序出现、断层都无法利用到多列索引。
- 索引的区分度,主要是衡量索引值不相同的程度,区分度越大,越有利于索引的查询。
- 组合索引的顺序和区分度:对于多个列构成的组合索引,在查询过滤的时候也是和列的位置有关的,这也是最左前缀规则说的事情,也就是说如果在第一次能过滤掉大量的数据,那么后续的索引匹配就能减少很多消耗。所以在选择索引顺序的时候最好是要考虑到区分度的问题,将区分度比较高的列放在前面。
- 只有当索引的列顺序和Order By子句的顺序完全一致时,并且所有的列的排序方向都一样时,才能使用索引对子句进行排序。
- 应该注意的几点:在使用索引查询的时候,需要保证索引类型和查询的数据类型一致,经常混用的是用int型查询varchar类型的数据或反过来,这样会导致索引失效;range查询要尽量放在后面,因为在range后面的查询不会走索引,这一点在设计索引时要注意;Like查询不能前缀模糊匹配,也就是说不可以like ‘%123’,因为like的后缀模糊 like ‘123%’可以转化为range查询,但是前缀模糊不可以;索引不是越多越好,索引十分大时不仅会影响查询效率,同时会为数据的插入造成很大的负担;对于重复索引需要删除,规划好索引是高效率的前提。
- 主键索引和唯一索引的区别:主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键;主键不允许为空值,唯一索引列允许空值;一个表只能有一个主键,但是可以有多个唯一索引主键可以被其他表引用为外键,唯一索引列不可以;主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本质的差别。
2.MySql的事务隔离级别有哪几种?
- 隔离级别用于表述并发事务之间的相互干扰程度,其基于锁机制进行并发控制。
- 可序列化(Serializable):事务一个接一个的执行,完全相互独立;实现可序列化要求在选定对象上的读锁和写锁保持直到事务结束后才能释放;在SELECT的查询中使用一个WHERE子句来描述一个范围时应该获得一个“范围锁”。
- 可重复度(Repeatable Read):事务A读取数据之后,对涉及的数据加锁,不允许其他事务进行修改,由于其他事务会插入新的数据,因此会产生幻读;对选定对象的读锁和写锁一直保持到事务结束,但不要求“范围锁”,因此可能会发生幻读;可重复读是MySQL的默认事务隔离级别。
- 读取已提交(Read Committed):只能看到其他事务已经提交的数据,避免了脏读,但存在不可重复读、幻读;DBMS需要对选定对象的写锁(write locks)一直保持到事务结束,但是读锁(read locks)在SELECT操作完成后马上释放,且不要求“范围锁”。
- 读取未提交(Read Uncommitted):可以看到其他事务没有提交的数据,出现脏读、不可重复读、幻读;
[PS补充]
不可重复读的重点是修改:同样的条件,读取过的数据,再次读取出来发现值不一样了。
幻读的重点在于新增或者删除:同样的条件,第1次和第2次读出来的记录数不一样。
3.MySql的MVVC有什么作用?
- 多版本并发控制(MVCC),来实现MySQL上的多事务并发访问时,隔离级别控制;
- 数据版本:并发事务执行时,同一行数据有多个版本;
- 事务版本:每个事务都有一个事务版本;
- 版本有序:版本是通过时间来标识的;
- 通过MVCC实现的效果是同一时刻、同一张表、多个并发事务,看到的数据是不同的。
- MVCC本质使用了copy-on-write,为每个数据保留多份snapshot,不同snapshot之间,使用指针连接成链表;update操作,能看到的snapshot是受限的,是链表上小于等于当前事务版本的最大版本(读取已提交:离当前事务最近的已提交版本);