MySQL 面试题

MySQL 面试题汇总

1.说一下 MySQL 执行一条查询语句的内部执行过程?

MySQL 执行一条查询的流程如下:

  • 客户端先通过连接器连接到 MySQL 服务器;
  • 连接器权限验证通过之后,先查询是否有查询缓存,如果有缓存(之前执行过此语句)则直接返回缓存数据,如果没有缓存则进入分析器;
  • 分析器会对查询语句进行语法分析和词法分析,判断 SQL 语法是否正确,如果查询语法错误会直接返回给客户端错误信息,如果语法正确则进入优化器;
  • 优化器是对查询语句进行优化处理,例如一个表里面有多个索引,优化器会判别哪个索引性能更好;
  • 优化器执行完就进入执行器,执行器则开始执行语句进行查询比对了,直到查询到满足条件的所有数据,然后进行返回。

2.MySQL 查询缓存有什么优缺点?

MySQL 查询缓存功能是在连接器之后发生的,它的优点是效率高,如果已经有缓存则会直接返回结果。

查询缓存的缺点是失效太频繁导致缓存命中率比较低,任何更新表操作都会清空查询缓存,因此导致查询缓存非常容易失效。

3.MySQL 的常用引擎都有哪些?

MySQL 的常用引擎有 InnoDB、MyISAM、Memory 等,从 MySQL 5.5.5 版本开始 InnoDB 就成为了默认的存储引擎。

4.常用的存储引擎 InnoDB 和 MyISAM 有什么区别?

答:InnoDB 和 MyISAM 最大的区别是 InnoDB 支持事务,而 MyISAM 不支持事务,它们其他主要区别如下:

  • InnoDB 支持崩溃后安全恢复,MyISAM 不支持崩溃后安全恢复;
  • InnoDB 支持行级锁,MyISAM 不支持行级锁,只支持到表锁;
  • InnoDB 支持外键,MyISAM 不支持外键;
  • MyISAM 性能比 InnoDB 高;
  • MyISAM 支持 FULLTEXT 类型的全文索引,InnoDB 不支持 FULLTEXT 类型的全文索引,但是 InnoDB 可以使用 sphinx 插件支持全文索引,并且效果更好;
  • InnoDB 主键查询性能高于 MyISAM。

5.什么叫回表查询?

普通索引查询到主键索引后,回到主键索引树搜索的过程,我们称为回表查询。

6.如果把一个 InnoDB 表的主键删掉,是不是就没有主键,就没办法进行回表查询了?

不是,如果把主键删掉了,那么 InnoDB 会自己生成一个长度为 6 字节的 rowid 作为主键。

7.什么是独立表空间和共享表空间?它们的区别是什么?

共享表空间指的是数据库的所有表数据,索引文件全部放在一个文件中,默认这个共享表空间的文件路径在 data 目录下。

独立表空间:每一个表都将会生成以独立的文件方式来进行存储。

共享表空间和独立表空间最大的区别是如果把表放再共享表空间,即使表删除了空间也不会删除,因此表依然很大,而独立表空间如果删除表就会清除空间。

8 清空表的所有数据性能最好的语句是?

truncate table t

truncate 清除表数据不会写日志,delete 要写日志,因此 truncate 的效率要高于 delete。

9.唯一索引和普通索引哪个性能更好?

唯一索引和普通索引的性能对比分为以下两种情况:

  • 对于查询来说两者都是从索引树进行查询,性能几乎没有任何区别;
  • 对于更新操作来说,因为唯一索引需要先将数据读取到内存,然后需要判断是否有冲突,因此比唯一索引要多了判断操作,从而性能就比普通索引性能要低。

10.left join 和 right join 的区别是什么?

答:left join 和 right join 的区别如下:

  • left join(左联结),返回左表全部记录和右表联结字段相等的记录;
  • right join(右联结),返回右表全部记录和左表联结字段相等的记录。

12.什么是最左匹配原则?它的生效原则有哪些?

最左匹配原则也叫最左前缀原则,是 MySQL 中的一个重要原则,指的是索引以最左边为起点任何连续的索引都能匹配上,当遇到范围查询(>、<、between、like)就会停止匹配。 生效原则来看以下示例,比如表中有一个联合索引字段 index(a,b,c):

  • where a=1 只使用了索引 a;
  • where a=1 and b=2 只使用了索引 a,b;
  • where a=1 and b=2 and c=3 使用a,b,c;
  • where b=1 or where c=1 不使用索引;
  • where a=1 and c=3 只使用了索引 a;
  • where a=3 and b like ‘xx%’ and c=3 只使用了索引 a,b。

13 or 查询有什么问题吗?该如何优化?

select * from t where num=10 or num=20;

如果使用 or 查询会使 MySQL 放弃索引而全表扫描,可以改为:

1
2
3
4
5
select * from t where num=10

union

select * from t where num=20;

14.事务是什么?它有什么特性?

事务是一系列的数据库操作,是数据库应用的基本单位。

在 MySQL 中只有 InnoDB 引擎支持事务,它的四个特性如下:

  • 原子性(Atomic),要么全部执行,要么全部不执行;
  • 一致性(Consistency),事务的执行使得数据库从一种正确状态转化为另一种正确状态;
  • 隔离性(Isolation),在事务正确提交之前,不允许把该事务对数据的任何改变提供给其他事务;
  • 持久性(Durability),事务提交后,其结果永久保存在数据库中。

15.MySQL 中有几种事务隔离级别?分别是什么?

MySQL 中有四种事务隔离级别,分别是:

  • read uncommited,未提交读,读到未提交数据;
  • read committed,读已提交,也叫不可重复读,两次读取到的数据不一致;
  • repetable read,可重复读;
  • serializable,串行化,读写数据都会锁住整张表,数据操作不会出错,但并发性能极低,开发中很少用到。

MySQL 默认使用 repetable read 的事务隔离级别。

16.如何设置 MySQL 的事务隔离级别?

MySQL 事务隔离级别 mysql.cnf 文件里设置的(默认目录 /etc/my.cnf),在文件的文末添加配置:

transaction-isolation = REPEATABLE-READ

可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。

17.MySQL 出现了中文乱码该如何解决?

解决 MySQL 中文乱码的问题,可以设置全局编码或设置某个数据库或表的编码为 utf8。 设置全局编码:

1
2
3
set character_set_client='utf8';
set character_set_connection='utf8';
set character_set_results='utf8';

18.InnoDB 为什么要使用 B+ 树,而不是 B 树、Hash、红黑树或二叉树?

因为 B 树、Hash、红黑树或二叉树存在以下问题。

  • B 树:不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致 IO 操作变多,查询性能变低。
  • Hash:虽然可以快速定位,但是没有顺序,IO 复杂度高。
  • 二叉树:树的高度不均匀,不能自平衡,查找效率跟数据有关(树的高度),并且 IO 代价高。
  • 红黑树:树的高度随着数据量增加而增加,IO 代价高。

19.MySQL 是如何处理死锁?

MySQL 对待死锁常见的两种策略:

  • 通过 innodb_lock_wait_timeout 来设置超时时间,一直等待直到超时;
  • 发起死锁检测,发现死锁之后,主动回滚死锁中的某一个事务,让其他事务继续执行。

20.什么是全局锁?它的应用场景有哪些?

全局锁就是对整个数据库实例加锁,它的典型使用场景就是做全量逻辑备份,这个时候整个库会处于完全的只读状态。

21.使用全局锁会导致什么问题?

使用全局锁会使整个系统不能执行更新操作,所有的更新业务会出于等待状态;如果你是在从库进行备份,则会导致主从同步严重延迟。

22.InnoDB 存储引擎有几种锁算法?

InnoDB 的锁算法包括以下三种:

  • Record Lock — 单个行记录上的锁;
  • Gap Lock — 间隙锁,锁定一个范围,不包括记录本身;
  • Next-Key Lock — 锁定一个范围,包括记录本身。

23.InnoDB 如何实现行锁?

只有通过索引条件检索数据,InnoDB 才使用行级锁,否则 InnoDB 将使用表锁。使用 for update 来实现行锁,具体脚本如下:

select * from t where id=1 for update

其中 id 字段必须有索引。

24.MySQL 性能指标都有哪些?如何得到这些指标?

MySQL 最重要的性能指标有以下两个:

  • QPS(Queries Per Second),每秒查询数,一台数据库每秒能够处理的查询次数;
  • TPS(Transactions Per Second),每秒处理事务数。

这些性能指标可以通过 show status 来查询当前数据库状态的结果信息中估算出来,show status 会有 300 多条状态信息记录,其中以下这些信息 QPS 和 TPS 有关系:

Uptime,服务器已经运行的时间,单位秒;
Questions,已经发送给数据库查询数;
Com_select,查询次数,实际查询次数;
Com_insert,插入次数;
Com_delete,删除次数;
Com_update,更新次数;
Com_commit,事务次数;
Com_rollback,回滚次数。

25.如何定位慢查询?

使用sql执行计划 explain

explain select * from t where id=5;
在这里插入图片描述

其中:

id — 选择标识符,id 越大优先级越高,越先被执行
select_type — 表示查询的类型。
table — 输出结果集的表
partitions — 匹配的分区
type — 表示表的连接类型
possible_keys — 表示查询时,可能使用的索引
key — 表示实际使用的索引
key_len — 索引字段的长度
ref— 列与索引的比较
rows — 大概估算的行数
filtered — 按表条件过滤的行百分比
Extra — 执行情况的描述和说明

其中最重要的就是 type 字段,type 值类型如下:

all — 扫描全表数据
index — 遍历索引
range — 索引范围查找
index_subquery — 在子查询中使用 ref
unique_subquery — 在子查询中使用 eq_ref
ref_or_null — 对 null 进行索引的优化的 ref
fulltext — 使用全文索引
ref — 使用非唯一索引查找数据
eq_ref — 在 join 查询中使用主键或唯一索引关联
const — 将一个主键放置到 where 后面作为条件查询, MySQL 优化器就能把这次查询优化转化为一个常量,如何转化以及何时转化,这个取决于优化器,这个比 eq_ref 效率高一点

26.MySQL 中常见的读写分离方案有哪些?

MySQL 中常见的读写分离方案

  • 使用 MySQL 官方提供的数据库代理产品 MySql ProxySQL 搭建自动分配的数据库读写分离环境;
  • 或者使用中间件myCat 等 (推荐使用)
  • 在程序层面配置多数据源使用代码实现读写分离(扩展性差,需要动代码)。

27.表的优化策略有哪些?

  • 读写分离,主库负责写,从库负责读。
  • 垂直分区,根据数据属性单独拆表甚至单独拆库。
  • 水平分区,保持表结构不变,根据策略存储数据分片,这样每一片数据被分散到不同的表或者库中。水平拆分只是解决了单一表数据过大的问题,表数据还在同一台机器上,对于并发能力没有什么意义,因此水平拆- 分最好分库。另外分片事务难以解决,跨节点 join 性能较差。

28.查询语句的优化方案有哪些?

  • 不做列运算,把计算都放入各个业务系统实现;
  • 查询语句尽可能简单,大语句拆小语句,减少锁时间;
  • 不使用 select * 查询;
  • or 查询改写成 in 查询;
  • 不用函数和触发器;
  • 避免 %xx 查询;
  • 少用 join 查询;
  • 使用同类型比较,比如 ‘123’ 和 ‘123’、123 和 123;
  • 尽量避免在 where 子句中使用 != 或者 <> 操作符,查询引用会放弃索引而进行全表扫描;
  • 列表数据使用分页查询,每页数据量不要太大。

29.MySQL 毫无规律的异常重启,可能产生的原因是什么?该如何解决?

可能是积累的长连接导致内存占用太多,被系统强行杀掉导致的异常重启,因为在 MySQL 中长连接在执行过程中使用的临时内存对象,只有在连接断开的时候才会释放,这就会导致内存不断飙升,解决方案如下:

定期断开空闲的长连接;

如果是用的是 MySQL 5.7 以上的版本,可以定期执行 mysql_reset_connection 重新初始化连接资源,这个过程会释放之前使用的内存资源,恢复到连接刚初始化的状态。