MySQL面试专题(一)

MySQL 基础模块的面试题总结

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

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

MySQL 提示“不存在此列”是执行到哪一个节点报出的?

此错误是执行到分析器阶段报出的,由于 MySQL 会在分析器阶段检查 SQL 语句的正确性。面试

MySQL 查询缓存的功能有何优缺点?

MySQL 查询缓存功能是在链接器以后发生的,它的优势是效率高,若是已经有缓存则会直接返回结果。 查询缓存的缺点是失效太频繁致使缓存命中率比较低,任何更新表操做都会清空查询缓存,所以致使查询缓存很是容易失效。正则表达式

如何关闭 MySQL 的查询缓存功能?

MySQL 查询缓存默认是开启的,配置 querycachetype 参数为 DEMAND(按需使用)关闭查询缓存,MySQL 8.0 以后直接删除了查询缓存的功能。redis

MySQL 的经常使用引擎都有哪些?

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

MySQL 能够针对表级别设置数据库引擎吗?怎么设置?

能够针对不一样的表设置不一样的引擎。在 create table 语句中使用 engine=引擎名(好比Memory)来设置此表的存储引擎。完整代码以下:数据库

create table student( id int primary key auto_increment, username varchar(120), age int ) ENGINE=Memory

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

InnoDB 和 MyISAM 最大的区别是 InnoDB 支持事务,而 MyISAM 不支持事务,它们主要区别以下:缓存

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

InnoDB 有哪些特性?

1)插入缓冲(insert buffer):对于非汇集索引的插入和更新,不是每一次直接插入索引页中,而是首先判断插入的非汇集索引页是否在缓冲池中,若是在,则直接插入,不然,先放入一个插入缓冲区中。好似欺骗数据库这个非汇集的索引已经插入到叶子节点了,而后再以必定的频率执行插入缓冲和非汇集索引页子节点的合并操做,这时一般能将多个插入合并到一个操做中,这就大大提升了对非汇集索引执行插入和修改操做的性能。安全

2)两次写(double write):两次写给 InnoDB 带来的是可靠性,主要用来解决部分写失败(partial page write)。doublewrite 有两部分组成,一部分是内存中的 doublewrite buffer ,大小为 2M,另一部分就是物理磁盘上的共享表空间中连续的 128 个页,即两个区,大小一样为 2M。当缓冲池的做业刷新时,并不直接写硬盘,而是经过 memcpy 函数将脏页先拷贝到内存中的 doublewrite buffer,以后经过 doublewrite buffer 再分两次写,每次写入 1M 到共享表空间的物理磁盘上,而后立刻调用 fsync 函数,同步磁盘。以下图所示服务器

avatar

3)自适应哈希索引(adaptive hash index):因为 InnoDB 不支持 hash 索引,但在某些状况下 hash 索引的效率很高,因而出现了 adaptive hash index 功能, InnoDB 存储引擎会监控对表上索引的查找,若是观察到创建 hash 索引能够提升性能的时候,则自动创建 hash 索引。并发

一张自增表中有三条数据,删除了两条数据以后重启数据库,再新增一条数据,此时这条数据的 ID 是几?

若是这张表的引擎是 MyISAM,那么 ID=4,若是是 InnoDB 那么 ID=2(MySQL 8 以前的版本)。函数

MySQL 中什么状况会致使自增主键不能连续?

如下状况会致使 MySQL 自增主键不能连续:

  • 惟一主键冲突会致使自增主键不连续;
  • 事务回滚也会致使自增主键不连续。

InnoDB 中自增主键能不能被持久化?

自增主键能不能被持久化,说的是 MySQL 重启以后 InnoDB 能不能恢复重启以前的自增列,InnoDB 在 8.0 以前是没有持久化能力的,但 MySQL 8.0 以后就把自增主键保存到 redo log(一种日志类型,下文会详细讲)中,当 MySQL 重启以后就会从 redo log 日志中恢复。

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

共享表空间:指的是数据库的全部的表数据,索引文件所有放在一个文件中,默认这个共享表空间的文件路径在 data 目录下。 独立表空间:每个表都将会生成以独立的文件方式来进行存储。 共享表空间和独立表空间最大的区别是若是把表放再共享表空间,即便表删除了空间也不会删除,因此表依然很大,而独立表空间若是删除表就会清除空间。

如何设置独立表空间?

独立表空间是由参数 innodbfileper_table 控制的,把它设置成 ON 就是独立表空间了,从 MySQL 5.6.6 版本以后,这个值就默认是 ON 了。

如何进行表空间收缩?

使用重建表的方式能够收缩表空间,重建表有如下三种方式:

  • alter table t engine=InnoDB
  • optmize table t
  • truntace table t

说一下重建表的执行流程?

  • 创建一个临时文件,扫描表 t 主键的全部数据页;
  • 用数据页中表 t 的记录生成 B+ 树,存储到临时文件中;
  • 生成临时文件的过程当中,将全部对 t 的操做记录在一个日志文件(row log)中;
  • 临时文件生成后,将日志文件中的操做应用到临时文件,获得一个逻辑数据上与表 t相同的数据文件;
  • 用临时文件替换表 t 的数据文件。

表的结构信息存在哪里?

表结构定义占有的存储空间比较小,在 MySQL 8 以前,表结构的定义信息存在以 .frm 为后缀的文件里,在 MySQL 8 以后,则容许把表结构的定义信息存在系统数据表之中。

什么是覆盖索引?

覆盖索引是指,索引上的信息足够知足查询请求,不须要再回到主键上去取数据。

若是把一个 InnoDB 表的主键删掉,是否是就没有主键,就没办法进行回表查询了?

能够回表查询,若是把主键删掉了,那么 InnoDB 会本身生成一个长度为 6 字节的 rowid 做为主键。

执行一个 update 语句之后,我再去执行 hexdump 命令直接查看 ibd 文件内容,为何没有看到数据有改变呢?

多是由于 update 语句执行完成后,InnoDB 只保证写完了 redo log、内存,可能还没来得及将数据写到磁盘。

内存表和临时表有什么区别?

  • 内存表,指的是使用 Memory 引擎的表,建表语法是 create table … engine=memory。这种表的数据都保存在内存里,系统重启的时候会被清空,可是表结构还在。除了这两个特性看上去比较“奇怪”外,从其余的特征上看,它就是一个正常的表。
  • 而临时表,可使用各类引擎类型 。若是是使用 InnoDB 引擎或者 MyISAM 引擎的临时表,写数据的时候是写到磁盘上的。

并发事务会带来哪些问题?

  • 脏读
  • 修改丢失
  • 不可重复读
  • 幻读

什么是脏读和幻读?

脏读是一个事务在处理过程当中读取了另一个事务未提交的数据;幻读是指同一个事务内屡次查询返回的结果集不同(好比增长了或者减小了行记录)。

为何会出现幻读?幻读会带来什么问题?

由于行锁只能锁定存在的行,针对新插入的操做没有限定,因此就有可能产生幻读。 幻读带来的问题以下:

  • 对行锁语义的破坏;
  • 破坏了数据一致性。

如何避免幻读?

使用间隙锁的方式来避免出现幻读。间隙锁,是专门用于解决幻读这种问题的锁,它锁的了行与行之间的间隙,可以阻塞新插入的操做 间隙锁的引入也带来了一些新的问题,好比:下降并发度,可能致使死锁。

如何查看 MySQL 的空闲链接?

在 MySQL 的命令行中使用 show processlist; 查看全部链接,其中 Command 列显示为 Sleep 的表示空闲链接,以下图所示:

avatar

MySQL 中的字符串类型都有哪些?

MySQL 的字符串类型和取值以下:

类型 取值范围
CHAR(N) 0~255
VARCHAR(N) 0~65536
TINYBLOB 0~255
BLOB 0~65535
MEDUIMBLOB 0~167772150
LONGBLOB 0~4294967295
TINYTEXT 0~255
TEXT 0~65535
MEDIUMTEXT 0~167772150
LONGTEXT 0~4294967295
VARBINARY(N) 0~N个字节的变长字节字符集
BINARY(N) 0~N个字节的定长字节字符集

VARCHAR 和 CHAR 的区别是什么?分别适用的场景有哪些?

VARCHAR 和 CHAR 最大区别就是,VARCHAR 的长度是可变的,而 CHAR 是固定长度,CHAR 的取值范围为1-255,所以 VARCHAR 可能会形成存储碎片。因为它们的特性决定了 CHAR 比较适合长度较短的字段和固定长度的字段,如身份证号、手机号等,反之则适合使用 VARCHAR。

MySQL 存储金额应该使用哪一种数据类型?为何?

MySQL 存储金额应该使用 decimal ,由于若是存储其余数据类型,好比float 有致使小数点后数据丢失的风险。

limit 3,2 的含义是什么?

去除前三条数据以后查询两条信息。

now() 和 current_date() 有什么区别?

now() 返回当前时间包含日期和时分秒,current_date() 只返回当前时间,以下图所示:

avatar

如何去重计算总条数?

使用 distinct 去重,使用 count 统计总条数,具体实现脚本以下:

select count(distinct f) from t

lastinsertid() 函数功能是什么?有什么特色?

lastinsertid() 用于查询最后一次自增表的编号,它的特色是查询时不须要不须要指定表名,使用 select last_insert_id() 便可查询,由于不须要指定表名因此它始终以最后一条自增编号为主,能够被其它表的自增编号覆盖。好比 A 表的最大编号是 10,lastinsertid() 查询出来的值为 10,这时 B 表插入了一条数据,它的最大编号为 3,这个时候使用 lastinsertid() 查询的值就是 3。

删除表的数据有几种方式?它们有什么区别?

删除数据有两种方式:delete 和 truncate,它们的区别以下:

  • delete 能够添加 where 条件删除部分数据,truncate 不能添加 where 条件只能删除整张表;
  • delete 的删除信息会在 MySQL 的日志中记录,而 truncate 的删除信息不被记录在 MySQL 的日志中,所以 detele 的信息能够被找回而 truncate 的信息没法被找回;
  • truncate 由于不记录日志因此执行效率比 delete 快。

delete 和 truncate 的使用脚本以下:

delete from t where username='redis'; truncate table t;

MySQL 中支持几种模糊查询?它们有什么区别?

MySQL 中支持两种模糊查询:regexp 和 like,like 是对任意多字符匹配或任意单字符进行模糊匹配,而 regexp 则支持正则表达式的匹配方式,提供比 like 更多的匹配方式。 regexp 和 like 的使用示例以下: select * from person where uname like '%SQL%';> select from person where uname regexp '.SQL*.';

MySQL 支持枚举吗?如何实现?它的用途是什么?

MySQL 支持枚举,它的实现方式以下:

create table t( sex enum('boy','grid') default 'unknown' );

枚举的做用是预约义结果值,当插入数据不在枚举值范围内,则插入失败,提示错误 Data truncated for column 'xxx' at row n 。

count(column) 和 count(*) 有什么区别?

count(column) 和 count() 最大区别是统计结果可能不一致,count(column) 统计不会统计列值为 null 的数据,而 count() 则会统计全部信息,因此最终的统计结果可能会不一样。

如下关于 count 说法正确的是?

A. count 的查询性能在各类存储引擎下的性能都是同样的。 B. count 在 MyISAM 比 InnoDB 的性能要低。 C. count 在 InnoDB 中是一行一行读取,而后累计计数的。 D. count 在 InnoDB 中存储了总条数,查询的时候直接取出。

答:C

为何 InnoDB 不把总条数记录下来,查询的时候直接返回呢?

由于 InnoDB 使用了事务实现,而事务的设计使用了多版本并发控制,即便是在同一时间进行查询,获得的结果也可能不相同,因此 InnoDB 不能把结果直接保存下来,由于这样是不许确的。

可否使用 show table status 中的表行数做为表的总行数直接使用?为何?

不能,由于 show table status 是经过采样统计估算出来的,官方文档说偏差可能在 40% 左右,因此 show table status 中的表行数不能直接使用。

如下哪一个 SQL 的查询性能最高?

A. select count(*) from t where time>1000 and time<4500 B. show table status where name='t' C. select count(id) from t where time>1000 and time<4500 D. select count(name) from t where time>1000 and time<4500

答:B 题目解析:由于 show table status 的表行数是估算出来,而其余的查询由于添加了 where 条件,即便是 MyISAM 引擎也不能直接使用已经存储的总条数,因此 show table status 的查询性能最高。

InnoDB 和 MyISAM 执行 select count(*) from t,哪一个效率更高?为何?

MyISAM 效率最高,由于 MyISAM 内部维护了一个计数器,直接返回总条数,而 InnoDB 要逐行统计。

在 MySQL 中有对 count(*) 作优化吗?作了哪些优化?

MySQL 有对 count() 进行优化,以 InnoDB 为例,在 InnoDB 中主键索引数的叶子节点是主键值,而普通索引的叶子节点则是主键值,因此普通索引数比主键索引数要小不少,而对于 count 查询来讲,每一个索引树的查询结果都是同样的,因此 MySQL 会选择最小的那颗树来遍历,以此来优化 count() 的查询。

在 InnoDB 引擎中 count(*)、count(1)、count(主键)、count(字段) 哪一个性能最高?

count(字段)<count(主键 id)<count(1)≈count(*) 题目解析:

  • 对于 count(主键 id) 来讲,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。
  • 对于 count(1) 来讲,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。
  • 对于 count(字段) 来讲,若是这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;若是这个“字段”定义容许为 null,那么执行的时候,判断到有多是 null,还要把值取出来再判断一下,不是 null 才累加。
  • 对于 count() 来讲,并不会把所有字段取出来,而是专门作了优化,不取值。count() 确定不是 null,按行累加。

因此最后得出的结果是:count(字段)<count(主键 id)<count(1)≈count(*)。

MySQL 中内链接、左链接、右链接有什么区别?

  • 内连(inner join)— 把匹配的关联数据显示出来;
  • 左链接(left join)— 把左边的表所有显示出来,右边的表显示出符合条件的数据;
  • 右链接(right join)— 把右边的表所有显示出来,左边的表显示出符合条件的数据;

什么是视图?如何建立视图?

视图是一种虚拟的表,具备和物理表相同的功能,能够对视图进行增、改、查操做。视图一般是一个表或者多个表的行或列的子集。 视图建立脚本以下:

create view vname as select column_names from table_name where condition

视图有哪些优势?

  • 获取数据更容易,相对于多表查询来讲;
  • 视图可以对机密数据提供安全保护;
  • 视图的修改不会影响基本表,提供了独立的操做单元,比较轻量。

MySQL 中“视图”的概念有几个?分别表明什么含义?

MySQL 中的“视图”概念有两个,它们分别是:

  • MySQL 中的普通视图也是咱们最经常使用的 view,建立语法是 create view ...,它的查询和普通表同样;
  • InnoDB 实现 MVCC(Multi-Version Concurrency Control)多版本并发控制时用到的一致性读视图,它没有物理结构,做用是事务执行期间定于能够看到的数据。

使用 delete 误删数据怎么找回?

能够用 Flashback 工具经过闪回把数据恢复回来。

Flashback 恢复数据的原理是什么?

Flashback 恢复数据的原理是是修改 binlog 的内容,拿回原库重放,从而实现数据找回。

相关文章
相关标签/搜索