基础模块
1. MySQL执行一条查询语句的内部执行过程
客户端先通过连接器连接到MySQL服务器;
连接器权限验证通过后,先查询是否有查询缓存 ,如果有缓存(之前执行过此语句),则直接返回缓存数据,如果没有缓存则进入分析器;
分析器会对产讯语句进行语法分析和词法分析,判断SQL语法是否正确,如果查询语法错误,会直接返回给客户端错误信息,如果语法正确则进入优化器;
优化器是对查询语句进行优化处理,例如一个表里有多个索引,优化器会判别哪个索引性能更好;
优化器执行完,就进入执行器,执行器就开始执行语句进行查询对比了,直到查询到满足条件的所有数据,然后进行返回。
2. MySQL提示“不存在此列”是执行到了哪一个节点报出的
- 此错误是执行到分析器阶段报出的,因为MySQL会在分析器阶段检查SQL语句的正确性。
3. MySQL查询缓存的功能有何优缺点
查询缓存是在连接器之后发生的,优点是效率高,如果有缓存就会直接返回结果;
查询缓存的缺点是失效太频繁导致缓存命中率比较低,任何更新表操作都会清空查询缓存,因此导致查询缓存非常容易失效。
4. 如何关闭MySQL的查询缓存功能
MySQL的查询缓存功能默认是开启的,配置
query cache type
参数为DEMAND(按需使用)
关闭查询缓存;MySQL8.0之后直接删除了查询缓存的功能
5. MySQL常用的引擎有哪些
InnoDB --- 5.5.5版本后InnoDB就称为了默认的存储引擎;
MyISAM
Memory
6. MySQL可以针对表级别设置数据库引擎吗?怎么设置?
- 可以针对不同的表设置不同的引擎,在
create table
语句中使用engine=引擎名(比如Memory)
来设置此表的存储引擎:
create table student(
id int primary key auto_increment,
username varchar(120),
age int
) ENGINE=Memory
7. 常用的存储引擎InnoDB和MyISAM有什么区别
-
InnoDB和 MyISAM区别:
InnoDB支持事务,而MyISAM不支持事务(最大的区别);
InnoDB支持崩溃后安全恢复,MyISAM不支持崩溃后安全恢复;
InnoDB支持行级锁,MyISAM不支持行级锁,只支持到表级锁;
InnoDB支持外键,MyISAM不支持外键;
MyISAM性能比InnoDB高;
MyISAM支持FULLTEXT类型的全文索引,InnoDB不支持FULLTEXT类型的全文索引,但是InnoDB可以使用sphinx插件支持全文索引,并且效果更好;
InnoDB 主键查询性能高于 MyISAM。
8. InnoDB有哪些特性
-
插入缓存(insert buffer):
对于非聚集索引的插入和更新,不是每一次直接插入索引页中,而是首先判断插入的非聚集索引页是否在缓冲池中,如果在,则直接插入,否则,先放入一个插入缓冲区中。
好似欺骗数据库这个非聚集的索引已经插入到叶子节点了,然后再以一定的频率执行插入缓冲和非聚集索引子节点的合并操作,这时通常能将多个插入合并到一个操作中,这就大大提高了对非聚集索引执行插入和修改操作的性能。
-
**两次写(double write): **
两次写给InnoDB 带来的是可靠性,主要用来解决部分写失败(partial page write)
double write有两部分组成,一部分是内存中的double write buffer,大小为2M;另外一部分就是物理磁盘上的共享表空间中连续的128个页,即两个区,大小同样为2M。
当缓冲池的作业刷新时,并不直接写硬盘,而是通过memcpy函数先将赃页先拷贝到内存中的double write buffer, 之后通过double write buffer再分两次写,每次写入1M到共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘。如下图:
- 自适应哈希索引(adaptive hash index):由于 InnoDB 不支持 hash 索引,但在某些情况下 hash 索引的效率很高,于是出现了 adaptive hash index 功能, InnoDB 存储引擎会监控对表上索引的查找,如果观察到建立 hash 索引可以提高性能的时候,则自动建立 hash 索引。
9. 一张自增表中有三条数据,删除了两条数据之后重启数据库,再新增一条数据,此时这条数据的 ID 是几
- 如果这张表的引擎是 MyISAM,那么 ID=4,如果是 InnoDB,如果是MySQL 8 之前的版本那么 ID=2,
如果是MySQL 8 之后的版本,那么ID=4
10. MySQL中什么情况会导致自增主键不能连续
唯一主键冲突会导致自增键不连续
事务回滚也会导致自增键不连续
11. InnoDB中自增主键能不能被持久化
自增主键能不能被持久化,说的是MySQL重启之后InnoDB能不能恢复重启之前的自增列;
InnoDB在8.0之前是没有持久化能力的,但MySQL8.0之后就把自增主键保存到redo log(一种日志类型)中,当MySQL重启之后就会从redo log 日志中恢复;
12. 什么是独立表空间和共享表空间,他们的区别是什么
共享表空间: 指的是数据库的所有表数据,索引文件全部放在一个文件中,默认这个共享表空间的文件路径在data目录下
独立表空间: 每一个表都将会生成以独立的文件方式来进行存储;
区别: 最大的区别是如果把表放在共享表空间,即使表删除了,空间也不会删除,所以表依然很大,而独立表空间如果删除表就会清除空间。
13. 如何设置独立表空间
- 独立表空间是由参数
innodb*file*per_table
控制的,把它设置成 ON 就是独立表空间了,从 MySQL 5.6.6 版本之后,这个值就默认是 ON 了。
14. 如何进行表空间收缩
使用重建表的方式可以收缩表空间,重建表有一下三种方式
alter table t engine=InnoDB
optmize table t
truntace table t
15. 说一下重建表的执行流程
建立一个临时文件,扫描表t主键的所有数据页;
用数据页中表t的记录生成B+树,存储到临时文件中;
生成临时文件的过程中,将所有对t的操作记录在一个日志文件(row log)中;
临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑上与表t相同的数据文件;
用临时文件替换表t的数据文件
16. 表的结构信息存在哪里
表结构定义占有的存储空间比较小
MySQL8之前,表结构的定义信息存在以.frm为后缀的文件里;
MySQL8之后,则允许把表结构的定义信息存在系统数据表之中;
17. 什么是覆盖索引
覆盖索引是指,索引上的信息足够满足查询请求,不需要再回到主键上去取数据
18. 如果把一个InnoDB表的主键删掉,是不是就没有主键,就没有办法进行回表查询了
可以回表查询,如果把主键删掉了,那么InnoDB会自己生成一个长度为6字节的rowid作为主键;
19. 执行一个 update 语句以后,我再去执行 hexdump 命令直接查看 ibd 文件内容,为什么没有看到数据有改变呢
可能是因为 update 语句执行完成后,InnoDB 只保证写完了 redo log,内存中的数据可能还没来得及将数据写到磁盘。
20. 内存表和临时表有什么区别?
-
**内存表: **
指的是使用 Memory 引擎的表,建表语法是 create table … engine=memory;
内存表的数据都保存在内存里,系统重启的时候会被清空,但是表结构还在;
-
临时表:
可以使用各种引擎类型
如果是使用 InnoDB 引擎或者 MyISAM 引擎的临时表,写数据的时候是写到磁盘上的。
21. 并发事务会带来哪些问题
脏读
修改丢失
不可重复读
幻读
22. 什么是脏读,幻读和不可重复读
脏读: 指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
幻读(针对insert和delete操作): 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
不可重复读(针对insert与update操作): 是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
**脏读、幻读、不可重复读: ** https://blog.csdn.net/qq_33591903/article/details/81672260
23. 为什么会出现幻读,幻读带来的问题,以及避免
https://blog.csdn.net/andyxm/article/details/44810417 (幻读和间隙锁)
原因: 因为行锁只能锁定存在的行,针对新插入的操作没有限定,所以就有可能产生幻读
-
问题:
对行锁语义的破坏
破坏了数据一致性
如何避免幻读
使用间隙锁的方式来避免出现幻读。
间隙锁,是专门用于解决幻读这种问题的锁,它锁的了行与行之间的间隙,能够阻塞新插入的操作 间隙锁的引入也带来了一些新的问题,比如:降低并发度,可能导致死锁。
24. 如何查看 MySQL 的空闲连接?
在 MySQL 的命令行中使用 show processlist;
查看所有连接,其中 Command 列显示为 Sleep 的表示空闲连接
25. 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个字节的定长字节字符集 |
26. VARCHAR 和 CHAR 的区别是什么?分别适用的场景有哪些?
VARCHAR 的长度是可变的,而 CHAR 是固定长度,CHAR 的取值范围为1-255,因此 VARCHAR 可能会造成存储碎片。
由于它们的特性决定了 CHAR 比较适合长度较短的字段和固定长度的字段,如身份证号、手机号等,反之则适合使用 VARCHAR。
27. MySQL 存储金额应该使用哪种数据类型?为什么?
MySQL 存储金额应该使用 decimal
,因为如果存储其他数据类型,比如 float
有导致小数点后数据丢失的风险。
28. limit 3,2 的含义是什么?
去除前三条数据之后查询两条信息。
29. now() 和 current_date() 有什么区别?
now() 返回当前时间包含日期和时分秒,current_date() 只返回当前时间
30. 如何去重计算总条数?
使用 distinct 去重,使用 count 统计总条数,具体实现脚本如下:
select count(distinct f) from t
31. last_insert_id()
函数功能是什么?有什么特点?
用于查询最后一次自增表的编号,它的特点是查询时不需要指定表名,使用
select last_insert_id()
即可查询,因为不需要指定表名所以它始终以最后一条自增编号为主,可以被其它表的自增编号覆盖。比如 A 表的最大编号是 10,lastinsertid() 查询出来的值为 10,这时 B 表插入了一条数据,它的最大编号为 3,这个时候使用 lastinsertid() 查询的值就是 3。
32. 删除表的数据有几种方式?它们有什么区别?
-
删除数据有两种方式: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;
33. MySQL 中支持几种模糊查询?它们有什么区别?
MySQL 中支持两种模糊查询:regexp 和 like
-
区别:
like 是对任意多字符匹配或任意单字符进行模糊匹配,而 regexp 则支持正则表达式的匹配方式,提供比 like 更多的匹配方式
示例
select * from person where uname like '%SQL%'; select from person where uname regexp '.SQL*.';
34. MySQL 支持枚举吗?如何实现?它的用途是什么?
- MySQL 支持枚举,它的实现方式如下:
create table t(
sex enum('boy','grid') default 'unknown'
);
- 枚举的作用是预定义结果值,当插入数据不在枚举值范围内,则插入失败,提示错误
Data truncated for column 'xxx' at row n
35. count(column) 和 count(*) 有什么区别?
count(column) 和 count() 最大区别是统计结果可能不一致:
count(column) 统计不会统计列值为 null 的数据
count() 则会统计所有信息
36. 以下关于 count 说法正确的是?
count 的查询性能在各种存储引擎下的性能都是一样的。(错误)
count 在 MyISAM 比 InnoDB 的性能要低。(错误)
count 在 InnoDB 中是一行一行读取,然后累计计数的。 (正确)
count 在 InnoDB 中存储了总条数,查询的时候直接取出。(错误)
37. 为什么 InnoDB 不把总条数记录下来,查询的时候直接返回呢?
因为 InnoDB 使用了事务实现,而事务的设计使用了多版本并发控制,即使是在同一时间进行查询,得到的结果也可能不相同,所以 InnoDB 不能把结果直接保存下来,因为这样是不准确的。
38. 能否使用 show table status 中的表行数作为表的总行数直接使用?为什么?
不能,因为 show table status 是通过采样统计估算出来的,官方文档说误差可能在 40% 左右,所以 show table status 中的表行数不能直接使用
39. 以下哪个 SQL 的查询性能最高?
select count(*) from t where time>1000 and time<4500 ;
show table status where name='t' ;
select count(id) from t where time>1000 and time<4500 ;
select count(name) from t where time>1000 and time<4500;
第二条性能最高;
题目解析:因为 show table status 的表行数是估算出来,而其他的查询因为添加了 where 条件,即使是 MyISAM 引擎也不能直接使用已经存储的总条数,所以 show table status 的查询性能最高。
40. InnoDB 和 MyISAM 执行 select count(*) from t
,哪个效率更高?为什么?
MyISAM 效率最高,因为 MyISAM 内部维护了一个计数器,直接返回总条数,而 InnoDB 要逐行统计
41. 在 MySQL 中有对 count(*)
做优化吗?做了哪些优化?
MySQL 有对 count() 进行优化,以 InnoDB 为例:
在 InnoDB 中主键索引数的叶子节点是主键值,而普通索引的叶子节点则是主键值,所以普通索引数比主键索引数要小很多,
而对于 count 查询来说,每个索引树的查询结果都是一样的,所以 MySQL 会选择最小的那颗树来遍历,以此来优化 count() 的查询。
42. 在 InnoDB 引擎中 count(*)、count(1)、count(主键)、count(字段) 哪个性能最高?
count(字段) 对于 count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。 对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。 对于 count(字段) 来说,如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是 null,还要把值取出来再判断一下,不是 null 才累加。 对于 内连(inner join)-------把匹配的关联数据显示出来; 左连接(left join) ------把左边的表全部显示出来,右边的表显示出符合条件的数据; 右连接(right join) ------把右边的表全部显示出来,左边的表显示出符合条件的数据; 视图是一种虚拟的表,具有和物理表相同的功能,可以对视图进行增、改、查操作。视图通常是一个表或者多个表的行或列的子集。 视图创建脚本如下: 获取数据更容易,相对于多表查询来说; 视图能够对机密数据提供安全保护; 视图的修改不会影响基本表,提供了独立的操作单元,比较轻量。 MySQL 中的“视图”概念有两个,它们分别是: MySQL 中的普通视图也是我们最常用的 view,创建语法是 create view ...,它的查询和普通表一样; InnoDB 实现 MVCC(Multi-Version Concurrency Control)多版本并发控制时用到的一致性读视图,它没有物理结构,作用是事务执行期间定于可以看到的数据。 可以用 Flashback 工具通过闪回把数据恢复回来。 Flashback 恢复数据的原理是是修改 binlog 的内容,拿回原库重放,从而实现数据找回。
count(*)
来说,并不会把全部字段取出来,而是专门做了优化,不取值。count(*)
肯定不是 null,按行累加。43. MySQL 中内连接、左连接、右连接有什么区别?
44. 什么是视图?如何创建视图?
create view vname as
select column_names
from table_name
where condition
45. 视图有哪些优点?
46. MySQL 中“视图”的概念有几个?分别代表什么含义?
47. 使用 delete 误删数据怎么找回?
48. Flashback 恢复数据的原理是什么?