2019最新21个MySQL高频面试题介绍
作者:yyucao
今天给大家分享 21 个 MySQL 面试题。
1、Mysql中有哪几种锁?
MyISAM 支持表锁,InnoDB 支持表锁和行锁,默认为行锁。
表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量 最低。
行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高。
2、Mysql支持事务吗?
在缺省模式下,MYSQL 是 autocommit 模式的,所有的数据库更新操作都会即时提交,所 以在缺省情况下,mysql 是不支持事务的。
但是如果你的 MYSQL 表类型是使用 InnoDB Tables 或 BDB tables 的话,你的 MYSQL 就可以 使用事务处理,使用 SET AUTOCOMMIT=0 就可以使 MYSQL 允许在非 autocommit 模式,在非autocommit 模式下,你必须使用 COMMIT 来提交你的更改,或者用 ROLLBACK 来回滚你的 更改。
示例如下:
START TRANSACTION; SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summmary=@A WHERE type=1; COMMIT;
3、Mysql查询是否区分大小写?
不区分。
SELECT VERSION(), CURRENT_DATE; SeLect version(), current_date; seleCt vErSiOn(), current_DATE;
这几个例子都是一样的,Mysql 不区分大小写。
4、列设置为 AUTO INCREMENT 时,如果在表中达到最大值,会发生什么情况?
答:它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。
5、一张表,里面有 ID 自增主键,当 insert 了 17 条记录之后,删除了第 15,16,17 条记录, 再把 Mysql 重启,再 insert 一条记录,这条记录的 ID 是 18 还是 15 ?
如果表的类型是 MyISAM,那么是 18。因为 MyISAM 表会把自增主键的最大 ID 记录到数据文件里,重启 MySQL 自增主键的最大ID 也不会丢失。
如果表的类型是 InnoDB,那么是 15。InnoDB 表只是把自增主键的最大 ID 记录到内存中,所以重启数据库或者是对表进行OPTIMIZE 操作,都会导致最大 ID 丢失。
6、数据库三范式是什么?
第一范式(1NF):字段具有原子性,不可再分。(所有关系型数据库系 统都满足第一范式数据库表中的字段都是单一属性的,不可再分)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足 第二范式(2NF)必须先满足第一范式(1NF)。要求数据库表中的每 个实例或行必须可以被惟一地区分。通常需要为表加上一个列,以存储 各个实例的惟一标识。这个惟一属性列被称为主关键字或主键。
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三 范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关 键字信息。>所以第三范式具有如下特征: >>1. 每一列只有一个 值 >>2. 每一行都能区分。>>3. 每一个表都不包含其他表已经包含 的非主关键字信息。
7、mysql 的复制原理以及流程?
答:Mysql 内建的复制功能是构建大型,高性能应用程序的基础。将 Mysql 的数据 分布到多个系统上去,这种分布的机制,是通过将 Mysql 的某一台主机的数据 复制到其它主机(slaves)上,并重新执行一遍来实现的。* 复制过程中一 个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将 更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志 可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主 服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生 的任何更新,然后封锁并等待主服务器通知新的更新。
过程如下 :
主服务器 把更新记录到二进制日志文件中。
从服务器把主服务器的二进制日志拷贝 到自己的中继日志(replay log)中。
从服务器重做中继日志中的时间, 把更新应用到自己的数据库上。
8、mysql 中 myISAM与 innodb 的区别?
事务支持 > MyISAM:强调的是性能,每次查询具有原子性,其执行数 度比 InnoDB 类型更快,但是不提供事务支持。> InnoDB:提供事 务支持事务,外部键等高级数据库功能。具有事务(commit)、回滚 (rollback)和崩溃修复能力(crash recovery capabilities)的事务安全 (transaction-safe (ACID compliant))型表。
InnoDB 支持行级锁,而 MyISAM 支持表级锁. >> 用户在操作 myisam 表时,select,update,delete,insert 语句都会给表自动 加锁,如果加锁以后的表满足 insert 并发的情况下,可以在表的尾部插 入新的数据。
InnoDB 支持 MVCC, 而 MyISAM 不支持。
InnoDB支持外键,而MyISAM不支持。
表主键,MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。InnoDB:如果没有设定主键或者非空唯一索引,就会 自动生成一个 6 字节的主键(用户不可见),数据是主索引的一部分,附 加索引保存的是主索引的值。
InnoDB 不支持全文索引,而 MyISAM 支持。
可移植性、备份及恢复,MyISAM:数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进 行操作。InnoDB:免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十 G 的时候就相对痛苦了。
存储结构,MyISAM:每个 MyISAM 在磁盘上存储成三个文件。第一 个文件的名字以表的名字开始,扩展名指出文件类型。.frm 文件存储表 定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名 是.MYI (MYIndex)。InnoDB:所有的表都保存在同一个数据文件 中(也可能是多个文件,或者是独立的表空间文件),InnoDB 表的大 小只受限于操作系统文件的大小,一般为 2GB。
9、MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?
Read Uncommitted(读取未提交内容) >> 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容) >> 这是大多数数据库系统的默认隔离级别(但不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的 commit,所以同一 select 可能返回不同结果。
Repeatable Read(可重读) >> 这是 MySQL 的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影”行。InnoDB 和 Falcon 存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control 间隙锁)机制解决了该问题。注:其实多版本只是解决不可重复读问题,而加上间隙锁(也就是它这里所谓的并发控制)才解决了幻读问题。
Serializable(可串行化) >> 这是最高的隔离级别,它通过强制事务 排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个 读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁 竞争。
10、[SELECT *] 和[SELECT 全部字段]的 2 种写法有何优缺点?
前者要解析数据字典,后者不需要
结果输出顺序,前者与建表列顺序相同,后者按指定字段顺序。
表字段改名,前者不需要修改,后者需要改
后者可以建立索引进行优化,前者无法优化
后者的可读性比前者要高
11、简述 Mybatis 的插件运行原理,以及如何编写一个插件?
Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、 Executor 这 4 种接口的插件,Mybatis 通过动态代理,为需要拦截的接口生成代理对象以实 现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是 InvocationHandler 的 invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后在给插件编写注解,指定 要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
12、#{}和${}的区别是什么?
{}是预编译处理,${}是字符串替换。
Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法 来赋值。
Mybatis 在处理${}时,就是把${}替换成变量的值。
使用#{}可以有效的防止 SQL 注入,提高系统安全性。
13、什么是索引?请简述常用的索引有哪些种类?
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。如果想按特定职员的姓来查找他或她,则在表中搜索所有的行相比,索引有助于更快地获取信息
通俗的讲,索引就是数据的目录,就像看书一样,假如我想看第三章第四节的内容,如果有目录,我直接翻目录,找到第三章第四节的页码即可。如果没有目录,我就需要将从书的开头开始,一页一页翻,直到翻到第三章第四节的内容。
MySQL索引的分类
我们根据对以列属性生成的索引大致分为两类:
单列索引:以该表的单个列,生成的索引树,就称为该表的单列索引
组合索引:以该表的多个列组合,一起生成的索引树,就称为该表的组合索引。
单列索引又有具体细的划分:
主键索引:以该表主键生成的索引树,就称为该表的主键索引。
唯一索引:以该表唯一列生成的索引树,就称为该表的唯一索引。
普通索引:以该表的普通列(非主键,非唯一列)生成的索引树,就称为该表的普通索引。
14、索引是个什么样的数据结构呢?
答:索引的数据结构和具体存储引擎的实现有关, 在MySQL中使用较多的索引有Hash索引,B+树索引等。而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引。
15、Hash索引和B+树所有有什么区别或者说优劣呢?
答:首先要知道Hash索引和B+树索引的底层实现原理:
hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据。
B+树底层实现是多路平衡查找树,对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据。
那么可以看出他们有以下的不同:
hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询。因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询。而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围。
hash索引不支持使用索引进行排序,原理同上。
hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测,AAAA和AAAAB的索引没有相关性。
hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询。
hash索引虽然在等值查询上较快,但是不稳定,性能不可预测。当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差。而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低。
因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度。而不需要使用hash索引。
16、上面提到了B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,什么是聚簇索引?
答:在B+树的索引中,叶子节点可能存储了当前的key值,也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引.。在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引,如果没有唯一键,则隐式的生成一个键来建立聚簇索引。当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因此不用再次进行回表查询。
17、非聚簇索引一定会回表查询吗?
答:不一定。这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。
举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询。
18、对MySQL的锁了解吗?
答:当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。
就像酒店的房间,如果大家随意进出,就会出现多人抢夺同一个房间的情况,而在房间上装上锁,申请到钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以再次使用。
19、MySQL都有哪些锁呢?像上面的例子进行锁定岂不是有点阻碍并发效率了?
答:从锁的类别上来讲,有共享锁和排他锁。
共享锁:又叫做读锁,当用户要进行数据的读取时,对数据加上共享锁,共享锁可以同时加上多个。
排他锁:又叫做写锁,当用户要进行数据的写入时,对数据加上排他锁,排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。
用上面的例子来说就是用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的。一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以。
锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁。他们的加锁开销从大大小,并发能力也是从大到小。
20、MySQL的binlog有有几种录入格式?分别有什么区别?
答:有三种格式,statement,row和mixed。
statement模式下,记录单元为语句。即每一个sql造成的影响会记录,由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制。
row级别下,记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大。
mixed,一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row。
此外,新版的MySQL中对row级别也做了一些优化,当表结构发生变化的时候,会记录语句而不是逐行记录。
21、一条sql执行过长的时间,你如何优化,从哪些方面?
1、查看sql是否涉及多表的联表或者子查询,如果有,看是否能进行业务拆分,相关字段冗余或者合并成临时表(业务和算法的优化)。
2、涉及链表的查询,是否能进行分表查询,单表查询之后的结果进行字段整合。
3、如果以上两种都不能操作,非要链表查询,那么考虑对相对应的查询条件做索引。加快查询速度。
4、针对数量大的表进行历史表分离(如交易流水表)。
5、数据库主从分离,读写分离,降低读写针对同一表同时的压力,至于主从同步,mysql有自带的binlog实现 主从同步。
6、explain分析sql语句,查看执行计划,分析索引是否用上,分析扫描行数等等。
更多MySQL面试题大家可以查看下面的相关链接