1.mysql常用的存储引擎有哪些,以及应用场景是什么?

MyISAM:
事务:不支持事务,所以每次查询都是原子的
行表锁:表锁,即使操作一条记录也会锁住整个表,不适合高并发的操作
缓存:只缓存索引,不缓存真实数据
表空间:小
关注点:性能

InnoDb:
事务:支持事务
行表锁:行锁,只锁一行数据,不会对其他行有影响,适合高并发操作
缓存:不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响
表空间:大
关注点:事务

2.mysql中有哪些锁?

表级锁:开销小,加锁快;不会出现死锁;锁定颗粒度大,发生锁冲突的概率最高
行级锁:开销大,加锁慢;会出现死锁;锁定颗粒度最小,发生锁冲突的概率最低,并发度也最高
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。

3.事务的四大特性?

原子性:原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚
一致性:一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
隔离性:隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
持久性:持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

4.Mysql中InnoDB支持的四种事务隔离级别名称,以及逐级之间的区别?

SQL标准定义的四个隔离级别为:
read uncommited :读未提交
事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

read committed:脏读,读已提交
事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

repeatable read:可重复读
系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
A事务多次查询一部分数据,多次查询的数据多了一条,查到了B事务插入的数据

serializable :串行化

注意:不可重复读和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需

5.CHAR和VARCHAR的区别?

1.CHAR和VARCHAR类型在存储和检索方面有所不同
2.CHAR列长度固定为创建表时声明的长度,长度值范围是1到255
当CHAR值被存储时,它们被用空格填充到特定长度,检索CHAR值时需删除尾随空格。

6.什么是慢查询?

慢查询日志,顾名思义,就是查询慢的日志,是指mysql记录所有执行超过long_query_time参数设定的时间阈值的SQL语句的日志。
该日志能为SQL语句的优化带来很好的帮助。默认情况下,慢查询日志是关闭的,要使用慢查询日志功能,首先要开启慢查询日志功能。

可以查看是否开启以及慢查询日志的地址
show variables like ‘%slow_query_log%’;

7.数据库优化的方法有什么?

软优化:
1.查询语句优化
2.优化子查询
3.使用索引
4.分解表
5.增加中间表
6.增加冗余字段
7.分析表,检查表,优化表
硬优化:
1.cpu,磁盘,内存
2.参数设置
3.分表分库+读写分离

8.聚集索引和非聚集索引区别?

聚集索引:索引中键值的逻辑顺序决定了表中相应行的物理顺序(表数据按照索引的顺序来存储的)。
主键索引
非聚集索引:索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同(表数据存储顺序与索引顺序无关)。
分成普通索引,唯一索引,全文索引。

非聚集索引的存储结构与前面是一样的,不同的是在叶子结点的数据部分存的不再是具体的数据,而数据的聚集索引的key。所以通过非聚集索引查找的过程是先找到该索引key对应的聚集索引的key,
然后再拿聚集索引的key到主键索引树上查找对应的数据,这个过程称为回表!

如果一张表没有聚集索引,那么它被称为“堆集”(Heap)。
这样的表中的数据行没有特定的顺序,所有的新行将被添加的表的末尾位置。

聚集索引是主键索引,用叶子存储行数据
非聚集索引是非主键索引,使用非
InnoDB聚集索引的叶子节点存储行记录
主键索引所对应的B+树,叶子节点存储了行数据

InnoDB普通索引的叶子节点存储主键值。

9.索引优化思路?

1.尽量使用短的列当作索引,因为每个节点存储的数据有限,短的列节点存储的数据多,可以减少树的高度,减少磁盘io的次数
2.索引不能创建的太多,每个索引都会生成一个b+树,太多会占用内存,而且删除数据所有的索引都要删除;可以扩展索引,可以使用组合索引,可以复用b+树

10.长字符串索引怎么优化?

使用全文索引,可以使用字符串前几位字符当作索引

11.什么是最左匹配原则?

前提是组合索引
最左优先,以最左边的为起点任何连续的索引都能匹配上。同时遇到范围查询(>、<、between、like)就会停止匹配。
对于组合索引,从左到右依次匹配,遇到> < betw

12.在电商平台的订单中心系统中,通常要根据商品类型、订单状态筛选出需要的订单,并按照订单创建的

时间来进行排序,那针对下面这条sql,你怎么通过索引来提高查询效率?

select * from order where status=1 order by create_time asc

最好的方式是:建立一个status和create_time组合索引
这是为了避免mysql数据库发生文件排序。因为在查询时,你只能用status的索引,但如果要对
create_time排序,就要用到文件排序filesort,也就是在sql执行计划中,Extra列会出现Using filesort
所以你要利用索引的有序性,在status和create_time列建立联合索引,这样根据status筛选后的数据就是按照
create_time排好序的,避免再文件排序

13.数据库索引底层使用的是什么数据结构和算法?

从数据结构的角度看,MySql常见的索引有

B+Tree索引: InnoDB引擎,MyISAM引擎、Memory引擎

HASH索引: Memory引擎

Full-Text索引:MyISAM引擎

Hash索引和B+Tree索引的区别:

14.为什么mysql innoDB选择B+Tree当默认的索引数据结构?

说B+树的原理以及对比其它的树的优点
每一层父节点的数据值都会出现在下层子节点的数据值中,因此在叶子节点中,包括了所有的数据值信息,
并且每一个叶子节点都指向下一个叶子节点,形成一个链表
B+Tree相比于B树和二叉树来说,最大的优势在于查询

15.如果表中没有主键,那么该表存在聚集索引吗?

如果表没有定义PK,则第一个not NULL unique列是聚集索引

16.如何理解索引覆盖,为什么可以提升查询效率?如何查看是否存在索引覆盖?

查询的时候不需要到聚集索引回表查询,就是索引覆盖,可以提高查询效率;使用执行计划查看

17.哪些场景可以利用索引覆盖来优化SQL?

场景1:全表count查询优化
场景1:列查询回表优化
场景1:分页查询

18.为什么要分库分表(设计高并发系统的时候,数据库层面应该如何设计)?

首先要清楚,分库和分表是两回事,是两个独立的概念。分库和分表都是为了防止数据库服务因为同一时间的访问量(增删查改)过大导致宕机而设计的一种应对策略。

为什么要分库:
按一般的经验来说,一个单库最多支持并发量到2000,
且最好保持在1000。如果有20000并发量的需求,这时就需要扩容了,
可以将一个库的数据拆分到多个库中,访问的时候根据一定条件访问单库,缓解单库的性能压力。

为什么要分表:
分表也是一样的,如果单表的数据量太大,就会影响SQL语句的执行性能。
分表就是按照一定的策略将单表的数据拆分到多个表中,
查询的时候也按照一定的策略去查询对应的表,
这样就将一次查询的数据范围缩小了。比如按照用户id来分表,将一个用户的数据就放在一个表中,crud先通过用户id找到那个表在进行操作就可以了。这样就把每个表的数据量控制在一定范围内,提升SQL语句的执行性能。

19.用过哪些分库分表的中间件?不同的分库分表中间件都有什么优点和缺点?

分库分表常见的中间件有:cobar、TDDL、atlas、sharding-jdbc和mycat等。
我用过sharding-jdbc。

20.具体如何对数据库进行垂直拆分或水平拆分?

水平拆分的意思:
就是把一个表的数据拆分到多个库的多个表里面去。这里面的每个库的表结构都是一样的,
只不过是表中存放的数据不一样,每个库表的数据汇总起来就是全部数据。
水平拆分的意义在于将数据均匀地存放在各个库表里,依靠多个库来杠更高的并发,
而且还能借助多个库的存储容量来进行扩容。

垂直拆分的概念:
垂直拆分的意思,就是把一个有很多字段的表给拆分成多个表或者多个库上面去,
每个库表的结构都不一样,每个库表都包含部分字段。一般来说,
会将较少的访问频率很高的字段放到一个表里面去,
然后将较多的访问频率很低的字段放到另外一个表里面去。因为数据库是有缓存的,
你访问频率高的行字段越少,就可以在缓存里面缓存更多的行,性能也就越好。
这个一般在表层面做的较多一些。

水平拆分和垂直拆分的场景:

所谓表层面的拆分,就是分表。
具体就是将一个表拆分为N个表,让每个表的数据量控制在一定的范围内,保证SQL的性能。
否则,单表的数据量越大,SQL的性能也就越差,一般是200万行左右,不要太多。
如果你的SQL越复杂,就尽量让单表的行数越少。
无论是分库还是分表,主流的数据库中间件都是可以支持的。
这些中间件可以在你分库分表之后,根据指定的某个字段值自动路由到对应的库和对应的表上面。
这时就只要考虑项目如何分库分表就行了。一般来说,垂直拆分,可以在表层面做,即对一些字段特别多的表做一下拆分;
水平拆分的话,可能是因为并发承载不了或容量承载不了,也就可以按某个字段去分布到不同的库表里面去。

21.分库分表的常用方案?

这里说一下两种分库分表的方案和它们的优缺点。
1.按照range来分。比如说按照时间范围来分库分表,每个库表中存放的都是连续时间范围的数据。
但是这种方式一般很少用,因为很容易会产生热点问题,大量的流量都打在最新的数据上了。这种方案的优点在于扩容的时候非常简单,比如只要预备好每个月都准备一个库就可以了,到了下一个新的月份自动将数据写入新的库。缺点则是,如果大部分请求都是访问最新的数据,那么在这里,
分库分表的设计目的就只是简单的扩容,而不是为了应对高并发了。

按照hash分发:
按照某个字段的hash值均匀分散,这个较为常用。
优点在于可以平均分配每个库表的数据量和请求压力;
缺点在于扩容比较麻烦,因为会存在一个数据迁移的过程,
即之前的数据需要重新计算hash值并重新分配到不同的库表中。