首先我个人属于在mysql上卡死一次又一次的人。。。毕竟小项目中,又不涉及什么高并发,所以什么表锁行锁压根不用想。甚至sql语句最多也就是个left join之类的,所以实际项目中sql优化近乎没有。当然了数据库设计更是可着怎么方便怎么来,三大范式完全就是个摆设。。总而言之,mysql一直对于我来说都是一个忽略的点。
然後面试的时候往深了问,一问一卡死。有时候会痛定思痛,前年有一段时间死磕MySQL,什么四大隔离级别啊,脏读幻读不可重复读啊,甚至关于B+树和hash我都自取其辱的仔细研究了下。至于索引,复合索引,索引失效等等,也都一个一个demo试过。
但是!说了这么多实战经验主要还是crud。然後没做过的东西靠死记硬背真的特别容易忘。吐了这么多槽只是为了表示对MySQL的重视,下面开始看关于MySQL的面试题。
1. MySQL中有几种锁?
- 表级锁:开销小,加锁快。不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢。会出现死锁。锁定粒度小,发生锁冲突的概率最低,并发度也最高。
- 页面锁:开销和加锁时间介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度一般。
2. MySQL中有哪些不同的表格?
共有五种类型的表格
- MyISAM
- Heap
- Merge
- INNODB
- ISAM
3. 简述在MySQL数据库中MyISAM和INNODB的区别
MyISAM:不支持事务,但是每次查询都是原子的。支持表级锁,即每次操作都是对整个表加锁。
存储表的总行数。
一个MYISAM表有三个文件:索引文件,表结构文件,数据文件。
采用非聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。
INNODB:支持ACID的事务,支持事务的四种隔离级别。
支持行级锁以及外键约束。因此可以支持写并发。
不存储总行数。
一个INNODB引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里。)。也有可能为多个(设置为独立表,表大小受操作系统文件大小限制,一般为2G).
主键索引采用聚集索引(索引的数据域存储数据文件本身)。辅索引的数据域存储主键的值。因为从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引。最好使用自增主键,防止插入数据时为维持B+树结构,文件的大调整。
4. MySQL中INNODB支持的四种食物隔离级别名称以及逐级之间的区别?
- read uncommited:读到未提交数据(读未提交)
- read commited: 读已提交
- repeatable read:可重复读
- serializable:串行事务
5. CHAR和VARCHAR的区别?
- CHAR和VARCHAR类型在存储和检索方面不同。
- CHAR列长度固定为创建表时声明的长度。长度值范围是1-255.当实际存储不足声明长度时它们被用空格填充到特定长度,检索CHAR值时需要删除尾随空格。
- VARCHAR是变长的。声明时的长度是可用最大值。
6. 主键和候选键有什么区别?
一个表只有一个主键。
主键也是候选键,按照惯例,候选键可以被指定为主键。并且可以用于任何外键引用。
7. myisamchk是用来做什么的?
用来压缩MyISAM表,者减少了磁盘或内存使用。
8. 问答题
MyISAM Static 和 MyISAM Dynamic 有什么区别?
- 在MyISAM Static上所有字段有固定宽度。 MyISAM Static在受损情况下更容易恢复。
- 动态MyISAM(MyISAM Dynamic) 表将具有像TEXT,BLOB等字段,以适应不同长度的数据类型。
如果一个表有一列定义为TIMESTAMP。将发生什么?
每当行被更改时,时间戳字段将获取当前时间戳。
列设置为AUTO INCREMENT时,如果在表中达到最大值,会发生什么情况?
它会停止递增,任何进一步的插入都将产生错误,因为秘钥已被使用。
怎样才能找出最后一次插入时分配了那个自动增量?
这个题的答案就是LAST_INSERT_ID()函数。将返回由Auto_increment分配 最后一个值。并且不需要指定表名称。
9. 你怎么看到为表格定义的所有索引?
命令行:show index from
当然了,比我我习惯用navicat,那么就直接设计表,然后有索引栏。
10. like声明中的%和_是什么意思?
%对应0或者更多个字符。而_代表一个字符。
比如 %xx%。则只要这个字段中包含xx就可以匹配到。
而xx。则必须是四个字符。且第二个,第三个字符是xx。
11. 列对比运算符是什么?
在SELECT语句的列比较中使用的,=, <>, <=, <, >=, >, <<, >>,<=>, AND, OR 或者LIKE运算符。
12. BLOB 和 TEXT有什么区别?
- BLOB是一个二进制对象,可容纳可变数量的数据。
- TEXT是一个不区分大小写的BLOB。
BLOB和TEXT类型之间的唯一区别在于对BLOB值进行排序和比较时是区分大小写的。而对TEXT值不区分大小写。
13. MyISAM表格将在哪里存储,并且还提供其存储格式?
每个MyISAM表格以三种格式存储在磁盘上:
- “.frm”文件存储表的定义
- 数据文件具有“.MYD”(myData)扩展名
- 索引文件具有“.MYI”(myIndex)扩展名
14. 如何查看sql语句的最终执行语句?
我们知道我们写的sql语句还会经过解析优化后再去执行,查看实际执行的语句方法(navicat中):
explain extended sql语句; -- 注意这个分号是必须的
show warnings
然后结果1是索引使用情况,结果2是实际执行语句。如下图:
15. 如何显示前50行?
在MySQL中,limit 0,50就是查询前50条。
其实分页的实现就是基于差不多的思路。
16. 可以使用多少列创建索引?
任何标准表最多可以创建16个索引列。
17. NOW()和 CURRENT_DATE()有什么区别?
now()方法用于显示当前年月日时分秒。而current_date()仅显示年月日。
18. 什么是非标准字符串类型?
- TINYTEXT
- TEXT
- MEDIUMTEXT
- LONGTEXT
19. 什么是通用SQL函数?
有一些函数所有数据库都支持的,叫做通用sql函数。如下:
-
CONCAT(A,B) 连接两个字符串值以创建单个字符串输出。通常用于将两个或者多个字段合并为一个字段。如下截图。
-
FORMAT(X,D) 格式化数字X到D有效数字。 当然了我个人是觉得这个其实用得不多,它的兄弟DATE_FORMAT用的倒是挺多的(我不知道这个是不是所有数据库都支持)。然后用法如下:
CURRDATE(),CURRTIME() 返回当前日期或者时间
NOW() 将当前日期和时间作为一个值返回
MONTH(),DAY(),YEAR(),WEEK(),WEEKDAY().从日期中提取给定数据。
HOUR(),MINUTE(),SECOND() 从时间中提取给定数据
-
DATEDIFF(A,B) 确定两个日期之间的差异,通常用于计算年龄。使用方法如下图:
-
SUBTIME(A,B) A时间戳减去B的时间。如下demo
-
FROMDAYS(int) 将整数天数转化为日期。这个天数好像是从366开始算一天。如下截图
20. MySQL支持事务么?
默认的缺省模式下,MySQL是autocommit模式的,所有数据库更新操作都会及时提交。所以缺省情况下是不支持事务的。
但是如果MySQL表类型是INNODB或者BDB的话,就可以使用事务处理。使用SET AUTOCOMMIT = 0就可以使MySQL允许在非autocommit模式。非autocommit模式下,必须使用commit来提交更改或者rollback来回滚更改。
21. MySQL里记录货币用什么字段类型好?
NUMERIC和DECIMAL类型被MySQL实现为同样的类型,这在SQL92标准允许。
他们被用于保存准确经度是极其重要的值。例如与金钱有关的数据。
当声明一个类是这些类型之一时,精度和规模能被指定。
比如 salary DECIMAL(9,2)。9代表存储值的总的位数。而2代表小数点后的位数。
这种情况下salary字段的值的范围是:-9999999.99到9999999.99。
22. MySQL有关权限的表都有哪几个?
MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在MySQL数据库里。由MySQL_install_db脚本初始化。这些权限表分别是:user,db,table_priv,columns_priv和host。
23. 列的字符串类型可以是什么?
- SET
- BLOB
- ENUM
- CHAR
- TEXT
24. MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?
- 设计两个的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率。
- 选择合适的表字段数据类型和存储引擎,适当的添加索引。
- MySQL库主从读写分离。
- 找规律分表,减少单表中的数据量提高查询速度。
- 添加缓存机制,比如memcached等。
- 不经常改动的页面生成静态页面。
- 书写高效率的SQL,比如不用select *。
25. 锁的优化策略
- 读写分离
- 分段加锁
- 减少锁持有的时间
- 多个线程尽量以相同的顺序去获取资源
不能将锁的粒度过于细化。不然可能会出现线程的加锁和释放次数过多,反而效率不如一次加一把大锁。
26. 索引的底层实现原理和优化
底层实现一般为hash或者B+树。(经过优化的B+树)
主要是在所有的叶子节点中增加了指向下一个叶子节点的指针。因此InnoDB建议大部分表使用默认自增的主键作为主索引。
27. 什么情况下设置了索引但无法使用?
- 以% 开头的like语句,模糊匹配
- OR语句前后没有同时使用索引
- 数据类型出现隐式转化(比如varchar不加单引号转成数字。)
28. 实践中如何优化MySQL
最好按照以下顺序优化:
- SQL语句以及索引的优化
- 数据库表结构的优化
- 系统配置的优化
- 硬件的优化
(附上一个阿里P8架构师写的优化总结:https://mikechen.cc/3305.html)
29. 优化数据库的方法
- 选取最适用的字段属性。尽可能的把字段设置为notnull。例如省份,性别等最好用枚举。
- 使用连接(join)来代替子查询。
- 使用联合(union) 来代替手动创建的临时表
- 事务处理
- 锁定表,优化事务处理
- 使用外键,优化锁定表
- 建立索引
- 优化查询语句
30. 简单描述MySQL中,索引,主键,唯一索引,联合索引的区别。对数据库的性能有什么影响(从读写两方面)
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表所有记录的引用指针。
普通索引(由关键字key或index定义的索引)的唯一任务就是加快对数据的访问速度。
普通索引允许被索引的数据列包含重复的值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。也就是说:唯一索引可以保证数据记录的唯一性。
主键是一种特殊的唯一索引。在一张表中只能定义一个主键索引。主键用于唯一标识一条记录。使用关键字primary key来创建。
索引可以覆盖多个数据列,如index(column A,columnB)索引,这个就是联合索引。
索引可以极大的提高数据的查询速度。但是会降低插入,删除和更新表的速度。因为在执行这些写操作时,还要操作索引文件。
31. 数据库中的事务是什么?
事务(transaction)是作为一个单元的一组有序的数据库操作。如果组中的所有操作都成功,则认为事务成功,即使只有一个操作失败,事务也不成功。如果所有操作完成,事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败则事务将回滚,该事务的所有操作的影响都将取消。
事务特性:
- 原子性:即不可分割性,要么全部被执行,要么全部不执行。
- 一致性或可串性:事务的执行使得数据库从一种正确状态转换成另一种正确状态。
- 隔离性:事务正确提交之前,不允许把该事务对数据库的任何改变提供给任何其他事务。
- 持久性:事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。
简而言之可以如下理解:
事务就是被绑定在一起作为一个逻辑单元的SQL语句组合,如果任何一个语句操作失败则整个操作都失败。就会回滚到操作前的状态(或者上个节点)。为了确保要么执行要么不执行就可以使用事务。要将一组语句作为事务考虑,就要通过ACID测试。即原子性,一致性,隔离性和持久性。
32, SQL注入漏洞产生的原因以及如何防止?
SQL注入产生的原因:程序开发过程中不规范书写sql语句和对特殊字符进行过滤,导致接口可以提交一些sql语句正常执行。(通俗点当我们把一些参数拼接到sql语句时,如果传过来的不是一个参数值而是sql的一部分。从而执行了和预计中完全不一样的sql)。
防止sql注入的方式也很多,简单说几种:
- 开启配置文件中magic_quotes_gpc和magic_quotes_runtime设置。
- sql语句书写尽量不要省略双引号和单引号。
- 过滤掉一些敏感词,比如update,insert,delete,select,where等。
- 对数据库表的命名和字段的命名不要太直白,尽量不让人猜到。
33. 为表中的字段选择合适的数据类型
字段类型优先级:整形>date,time>enum,char>varchar>blob,text
用言语讲就是优先考虑数字类型,其次是日期或者二进制类型,最后是字符串类型。同级别的数据类型应该优先选择占用空间小的数据类型。
34. 存储时期
- Datetime:以yyyy-MM-dd HH:mm:ss格式存储日期时间。精确到秒,占用8个字节的存储空间,datetime类型与时区无关系。
- Timestamp:以时间戳格式存储,占用四个字节。范围自1970/1/1到2038/1/19.显示依赖于所指定的时区。默认这行数据修改时可以自动的修改timestamp列的值。
- Date: 占用的字节数比字符串,datetime,int存储要少。使用date仅仅需要三个字符。存储年月日。还可以利用日期时间函数进行日期间的计算。
- Time:存储时间部分的数据。
注意:不要使用字符串类型来存储日期时间数据(因为日期类型比字符串占用的存储空间小,而且查找或者过滤,甚至一些时间计算上可以利用日期的函数。)
使用int存储时间日期不如使用timestamp类型。
35. 对于关系型数据库而言,索引是相当重要的概念,请回答以下几个问题:
索引的目的是什么?
快速访问数据库表中的特定信息。提高检索速度。
创建唯一性索引,保证数据库表中每一行数据的唯一性。
加速表和表之间的链接。
使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
索引对数据库系统的负面影响是什么?
创建索引和维护索引需要耗费时间,这个时间随着数据量的增加而增加。索引需要占用物理空间。不光是表需要占用数据空间,每个索引也需要占用物理空间。当对表进行增删改的时候索引也要动态维护,这样就降低了数据的维护速度。
为数据表建立索引的原则有哪些?
在最频繁使用的,用以缩小查询范围的字段上建立索引。
在频繁使用的,需要排序的字段上建立索引。
什么情况下不宜建立索引?
对于查询中很少涉及到的列或者重复制比较多的列不宜建立索引。
对于一些特殊的数据类型比如blob,text等,不宜建立索引。
36. 解释MySQL外连接,内连接与自连接的区别
这个必须要先说一下交叉连接:交叉连接又叫笛卡尔积,它是指不用任何条件,直接一个表的所有记录与另一个表的所有记录一一匹配。
内连接:是有条件的交叉连接。根据某个条件筛选出符合条件的记录,不符合条件的记录不会出现在结果集中,即内连接值连接匹配的行。(如下图)
外连接:如上图,结果集不仅包含共有部分,共有+左表数据属于左(外)连接。共有+右表数据属于右(外)连接。这些数据全部包含的属于全外连接。
左外连接和右外连接中另一个表没有的数据用null填充,MySQL目前不支持全外连接。
37. MySQL中事务回滚机制概述
事务是用户定义的一个数据库操作序列。这些操作要么不做,要么全做,是一个不可分割的工作单位。事务回滚是指将该事务已经完成的对数据库的更新操作撤销。
(正好这两天我遇到了一个生活着的事务的例子:叫外卖的时候之前看了一家的小菜挺好,加购以后要下单了才发现买这个小菜必须搭配某主食。我看了下主食并不想要,所以现在只有两个操作:1.把主食也加购,2,不买小菜了。这个主食和小菜我们可以理解成一个事务。要么全买,要么全不买。)
项目中,要同时修改数据库中两个不同表时,如果他们不是一个事务的话,当第一个表修改完,可能第二个表的修改因为某些原因没能修改。这个时候第一个表已经是修改完的状态,而第二个表是未修改状态。
而如果我们把这两个操作放到一个事务中,第一个表修改完,第二个表因为异常没能修改的话,第一个表和第二个表都回到未修改状态,这个就是事务的回滚。
38. SQL语句包括哪几部分?每部分都有哪些操作关键字?
SQL语句分四种:
- 数据定义DDL
- 数据操纵DML
- 数据控制DCL
- 数据查询DQL
数据定义DDL:CREATE TABLE, ALTER TABLE, DROP TABLE, CREATE/DROP INDEX等。(简单来说就是增删改表,索引)
数据操纵DML: SELECT, INSERT, UPDATE, DELETE等(简单来说增删改查记录)
数据控制DCL: GRANT, REVOKE(这两个比较少用到,是给数据库用户授权/撤销授权的)
数据查询DQL:SELECT
39. 完整性约束包括哪些?
数据完整性是指数据的精确和可靠性。
分为以下四类:
- 实体完整性: 规定表的每一行在表中是唯一的实体。
- 域完整性:是指表中的列必须满足某种特定的数据类型约束。其中约束又包括取值范围,精度等规定。
- 参照完整性: 是指两个表的主关键字和外关键字的数据应一致。保证了表之间的数据的一致性。防止了数据丢失或者无意义的数据在数据库中扩散。
- 用户定义的完整性: 不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件,用户定义的完整性即针对某个特定关系数据库的约束条件。它反映某一具体应用必须满足的语义要求。
与表有关的约束:列的非空约束。表的主键约束,唯一约束,指定类型约束,外键约束等。
40. 什么是锁?
数据库是一个多用户使用的共享资源。当多个用户并发的存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况,若对并发操作不加控制就可能会读取和存取不正确的数据,破坏数据库的一致性。
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在改事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
基本锁类型:表级锁和行级锁(这个第一个题好像就说了,还有个页面锁,其中优缺点都有介绍)
41. 什么叫视图?游标是什么?
视图是一种虚拟的表。具有和物理表相同的功能。可以对视图进行增/改/查操作。视图通常是由一个表或者多个表的行或列的子集。对视图的修改不影响基本表。
它使得我们获取数据更容易,相比于多表查询。
游标是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行。从结果集的当前行检索一行或者多行。可以对结果集当前行做修改。
一般不使用游标,但是当需要逐条处理数据的时候,游标显得极其重要。
42. 什么是存储过程?用什么来调用?
存储过程是一个预编译的SQL语句。优点是允许模块化的设计,就是说只需要创建一次以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯sql语句执行要快。可以用一个命令对象来调用存储过程。
43. 如何通俗的理解三个范式?
第一范式:列的不可再分。是对属性的原子性约束。要求属性具有原子性,不可再分解。举个例子:如果是存地址,可以分为省市区详细地址四个字段。而不是所有的地址放在一个字段。否则就是可再分的,不具有原子性。
第二范式:在满足第一范式的前提下,一行数据只做一件事。这个是对记录的唯一性约束。要求记录有唯一标识,即实体的唯一性。打个比方:我们常用的下订单功能:商品件数不定,但是订单就是一个订单。如果每个商品都保存这个订单的信息(订单号,下单时间,订单金额等)就是冗余。这个时候我们应该拆分成订单表和订单对应商品表。保证一个表只做一件事。
第三范式:满足1,2后,表中的每一列都直接与主键相关而不是间接相关。这个是对表的冗余性的约束。即任何字段不能由其他字段派生出来。它要求的是不要有冗余字段。这个怎么说呢,继续第二范式的例子:用户直接下订单。也就是用户和订单是有关系的。而订单包含商品,也就是订单和商品是有关系的。本质上用户购买的是商品,但是!!我们不应该在订单商品表中掺杂用户的信息。因为用户->订单->商品,这个是间接的关系了。
任何脱离实际的要求都是纯扯淡!注意这句话不是我说的,是阳哥(尚硅谷讲师周阳)说的。也就是实际上范式落实到实际中是不能百分百遵守的,完全按照范式来不见得会做出好东西。因为有时候实际的需求就是这么操蛋,阿里不都说了合理的冗余是必要的么!下面简单说下范式化设计的优缺点:
优点:可以尽量的减少数据冗余,使得更新快,体积小。如果数据异常,数据修改比较容易。
缺点:对于查询需要多个表进行关联,使得写更优化,但是读更复杂。更难进行索引优化。
44. 什么是基本表?什么是视图?
基本表是指本身独立存在的表,在SQL中一个关系就对应一个表。
视图是从一个或者几个基本表导出的表。视图本身不独立存储在数据库中,是一个虚表。
45. 视图的优点?
- 简化用户的操作
- 视图使用户能以多种角度看待同一个数据。
- 试图为数据库提供了一定程度的逻辑独立性
- 视图能够对机密数据提供安全保护。
46. null是什么意思?
null这个值表示的是unknown(未知),它不是“”(空串)。任何值与null值比较都会是null。我们可以使用is null 来进行null判断。
47. 主键/外键/索引的区别?
主键: 一条记录的唯一标识,不能有重复的,也不许为空。(主键约束包含非空和唯一约束。)
作用是用来保证数据的完整性。
一个表只能有一个主键。
外键:表的外键是另一个表的主键。可以有重复,也可以有空值。
作用是用来和其他表建立联系。
一个表可以有多个外键。
索引: 为了提高查询排序的速度而专门对一些列进行排序。
一个表可以有多个索引。
48. 你可以用什么来确保表里的字段只接受特定范围里的值?
可以用Check限制。他在数据库表里被定义,用来限制输入该列的值。
49. 简单说下对SQL语句优化的方法
- Where字句中,表之间的链接必须写在最前面。可以过滤掉最大数量记录的条件写在where子句的末尾。having写在最后。
- 用 exists代替in,用not exists代替not in
- 避免在索引上使用计算
- 避免在索引上使用 is null和 is not null
- 对查询进行优化,应该尽量避免全表扫描,首先应该考虑在where已经order by涉及的列上建立索引。
- 应尽量避免在where子句中对字段进行null判断,否则会放弃使用索引而进行全表扫描。
- 应尽量避免在where子句中对字段进行表达式操作,否则也会放弃使用索引而进行全表扫描。
至此,这本书中MySQL方面的面试题就结束啦!全文50个题目。其中一个现在已经很少用了所以我没记录。剩下别的其实也有很多重复的题目或者说比较老的题目,不过多看看总没有错!本篇笔记如果稍微帮到你了记得点个喜欢点个关注。也祝大家身体健健康康,工作顺利吧!