当前位置:网站首页>35道MySQL面试必问题图解,这样也太好理解了吧
35道MySQL面试必问题图解,这样也太好理解了吧
2022-07-31 17:00:00 【InfoQ】
关于面试题的文章之前发过不少,但读者们给的反馈是普遍是理解难,看完就忘。所以今天我会用画图来给大家分析一下这35道题,希望能够加深你们的理解。
篇幅所限,本文先写MySQL的35问,其他的技术栈我也都整理好了
我会把整理好的文档都无偿分享出来, +V MXD202007

1.说一说三大范式
- 「第一范式」:数据库中的字段具有「原子性」,不可再分,并且是单一职责
- 「第二范式」:「建立在第一范式的基础上」,第二范式要求数据库表中的每个实例或行必须「可以被惟一地区分」。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主键
- 「第三范式」:「建立在第一,第二范式的基础上」,确保每列都和主键列直接相关,而不是间接相关不存在其他表的非主键信息
但是在我们的日常开发当中,
「并不是所有的表一定要满足三大范式」
,有时候冗余几个字段可以少关联几张表,带来的查询效率的提升有可能是质变的
2.MyISAM 与 InnoDB 的区别是什么?

- 「InnoDB支持事务,MyISAM不支持」。
- 「InnoDB 支持外键,而 MyISAM 不支持」。
- 「InnoDB是聚集索引」,使用B+Tree作为索引结构,数据文件是和索引绑在一起的,必须要有主键。「MyISAM是非聚集索引」,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
- 「InnoDB 不保存表的具体行数」。「MyISAM 用一个变量保存了整个表的行数」。
- 5.Innodb 有 「redolog」 日志文件,MyISAM 没有
- 6.「Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI」Innodb:frm是表定义文件,ibd是数据文件Myisam:frm是表定义文件,myd是数据文件,myi是索引文件
- 「InnoDB 支持表、行锁,而 MyISAM 支持表级锁」
- 8、「InnoDB 必须有唯一索引(主键)」,如果没有指定的话 InnoDB 会自己生成一个隐藏列Row_id来充当默认主键,「MyISAM 可以没有」
3.为什么推荐使用自增 id 作为主键?

- 1.普通索引的 B+ 树上存放的是主键索引的值,如果该值较大,会「导致普通索引的存储空间较大」
- 2.使用自增 id 做主键索引新插入数据只要放在该页的最尾端就可以,直接「按照顺序插入」,不用刻意维护
- 3.页分裂容易维护,当插入数据的当前页快满时,会发生页分裂的现象,如果主键索引不为自增 id,那么数据就可能从页的中间插入,页的数据会频繁的变动,「导致页分裂维护成本较高」
4.一条查询语句是怎么执行的?

- 1.通过连接器跟客户端「建立连接」
- 2.通过查询「缓存查询」之前是否有查询过该 sql有则直接返回结果没有则执行第三步
- 3.通过分析器「分析该 sql 的语义」是否正确,包括格式,表等等
- 4.通过优化器「优化该语句」,比如选择索引,join 表的连接顺序
- 5.「验证权限」,验证是否有该表的查询权限没有则返回无权限的错误有则执行第六步
- 6.通过执行器调用存储引擎执行该 sql,然后返回「执行结果」
5.使用 Innodb 的情况下,一条更新语句是怎么执行的?
用以下语句来举例,c 字段无索引,id 为主键索引
update T set c=c+1 where id=2;- 1.执行器先找引擎取 id=2 这一行。id 是主键,引擎直接用树搜索找到这一行如果 id=2 这一行所在的数据页本来就「在内存中」,就「直接返回」给执行器「不在内存」中,需要先从磁盘「读入内存」,然后再「返回」
- 2.执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口「写入这行新数据」
- 3.引擎将这行新数据更新到内存中,同时将这个更新操作「记录到 redo log 里面」,此时 redo log 处于 「prepare」 状态。然后告知执行器执行完成了,随时可以提交事务
- 4.执行器「生成这个操作的 binlog」,并把 binlog 「写入磁盘」
- 5.执行器调用引擎的「提交事务」接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,「更新完成」
6.Innodb 事务为什么要两阶段提交?
- 先写 redolog 后写binlog。假设在 redolog 写完,binlog 还没有写完的时候,MySQL 进程异常重启,这时候 binlog 里面就没有记录这个语句。然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 「binlog 丢失」,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。
- 先写 binlog 后写 redolog。如果在 binlog 写完之后 crash,由于 redolog 还没写,崩溃恢复以后这个事务无效,所以这一行c的值是0。但是 binlog 里面已经记录了“把c从0改成1”这个日志。所以,在之后用 binlog 来恢复的时候就「多了一个事务出来」,恢复出来的这一行 c 的值就是 1,与原库的值不同。
可以看到,
「如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致」
。
7.什么是索引?
相信大家小时候学习汉字的时候都会查字典,想想你查字典的步骤,我们是通过汉字的首字母 a~z 一个一个在字典目录中查找,最终找到该字的页数。想想,如果没有目录会怎么样,最差的结果是你有可能翻到字典的最后一页才找到你想要找的字。
索引就
「相当于我们字典中的目录」
,可以极大的提高我们在数据库的查询效率。
8.索引失效的场景有哪些?
以下随便列举几个,不同版本的 mysql 场景不一
- 1.最左前缀法则(带头索引不能死,中间索引不能断
- 2.不要在索引上做任何操作(计算、函数、自动/手动类型转换),不然会导致索引失效而转向全表扫描
- 3.不能继续使用索引中范围条件(bettween、<、>、in等)右边的列,如:
select a from user where c > 5 and b = 4;- 4.索引字段上使用(!= 或者 < >)判断时,会导致索引失效而转向全表扫描
- 5.索引字段上使用 is null / is not null 判断时,会导致索引失效而转向全表扫描。
- 6.索引字段使用like以通配符开头(‘%字符串’)时,会导致索引失效而转向全表扫描,也是最左前缀原则。
- 7.索引字段是字符串,但查询时不加单引号,会导致索引失效而转向全表扫描
- 8.索引字段使用 or 时,会导致索引失效而转向全表扫描
9.为什么采用 B+ 树,而不是 B-树
B+ 树只在叶子结点储存数据,非叶子结点不存具体数据,只存 key,查询更稳定,增大了广度,而一个节点就是磁盘一个内存页,内存页大小固定,那么相比 B 树,B- 树这些
「可以存更多的索引结点」
,宽度更大,树高矮,节点小,拉取一次数据的磁盘 IO 次数少,并且 B+ 树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,效率更高。
10.WAl 是什么?有什么好处?
WAL 就是 Write-Ahead Logging,其实就是
「所有的修改都先被写入到日志中,然后再写磁盘」
,用于保证数据操作的原子性和持久性。
好处:
- 1.「读和写可以完全地并发执行」,不会互相阻塞
- 2.先写入 log 中,磁盘写入从「随机写变为顺序写」,降低了 client 端的延迟就。并且,由于顺序写入大概率是在一个磁盘块内,这样产生的 io 次数也大大降低
- 3.写入日志当数据库崩溃的时候「可以使用日志来恢复磁盘数据」
11.什么是回表?

回表就是先通过数据库索引扫描出该索引树中数据所在的行,取到主键 id,再通过主键 id 取出主键索引数中的数据,即基于非主键索引的查询需要多扫描一棵索引树.
12.什么是索引下推?
如果存在某些被索引的列的判断条件时,MySQL 将这一部分判断条件传递给存储引擎,然后由存储引擎通过判断索引是否符合 MySQL 服务器传递的条件,
「只有当索引符合条件时才会将数据检索出来返回给 MySQL 服务器」
。
13.什么是覆盖索引?
覆盖索引(covering index)指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取,可以减少回表的次数。比如:
select id from t where age = 1;id 为主键索引,age 为普通索引,age 这个索引树存储的就是逐渐信息,可以直接返回
14.什么是最左前缀原则?
最左前缀其实说的是,在 where 条件中出现的字段,
「如果只有组合索引中的部分列,则这部分列的触发索引顺序」
,是按照定义索引的时候的顺序从前到后触发,最左面一个列触发不了,之后的所有列索引都无法触发。
比如
「有一个 (a,b,c) 的组合索引」
where a = 1 and b = 1此时 a,b 会命中该组合索引
where a = 1 and c = 1此时 a 会命中该组合索引, c 不会
where b = 1 and c = 1此时不会命中该组合索引
15.普通索引和唯一索引该怎么选择?
- 查询当普通索引为条件时查询到数据会一直扫描,直到扫完整张表当唯一索引为查询条件时,查到该数据会直接返回,不会继续扫表
- 更新普通索引会直接将操作更新到 change buffer 中,然后结束唯一索引需要判断数据是否冲突
所以
「唯一索引更加适合查询的场景,普通索引更适合插入的场景」
16.什么是事务?其特性是什么?
事务是指是程序中一系列操作必须全部成功完成,有一个失败则全部失败。

特性
- 「1.原子性(Atomicity)」:要么全部执行成功,要么全部不执行。
- 「2.一致性(Consistency)」:事务前后数据的完整性必须保持一致。
- 「3.隔离性(Isolation)」:隔离性是当多个事务同事触发时,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
- 「4.持久性(Durability)」:事务完成之后的改变是永久的。
17.事务的隔离级别?
- 1.「读提交」:即能够「读取到那些已经提交」的数据
- 2.「读未提交」:即能够「读取到没有被提交」的数据
- 3.「可重复读」:可重复读指的是在一个事务内,最开始读到的数据和事务结束前的「任意时刻读到的同一批数据都是一致的」
- 4.「可串行化」:最高事务隔离级别,不管多少事务,都是「依次按序一个一个执行」

- 「脏读」脏读指的是「读到了其他事务未提交的数据」,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读
- 「不可重复读」对比可重复读,不可重复读指的是在同一事务内,「不同的时刻读到的同一批数据可能是不一样的」。
- 「幻读」幻读是针对数据插入(INSERT)操作来说的。假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现「好像刚刚的更改对于某些数据未起作用」,但其实是事务B刚插入进来的这就叫幻读
18.binlog 是做什么的?
binlog 是归档日志,属于 Server 层的日志,是一个二进制格式的文件,用于
「记录用户对数据库更新的SQL语句信息」
。
主要作用
- 主从复制
- 数据恢复
19.undolog 是做什么的?
undolog 是 InnoDB 存储引擎的日志,用于保证数据的原子性,
「保存了事务发生之前的数据的一个版本,也就是说记录的是数据是修改之前的数据,可以用于回滚」
,同时可以提供多版本并发控制下的读(MVCC)。
主要作用
- 事务回滚
- 实现多版本控制(MVCC)
20.relaylog 是做什么的?
relaylog 是中继日志,
「在主从同步的时候使用到」
,它是一个中介临时的日志文件,用于存储从master节点同步过来的binlog日志内容。

master 主节点的 binlog 传到 slave 从节点后,被写入 relay log 里,从节点的 slave sql 线程从 relaylog 里读取日志然后应用到 slave 从节点本地。从服务器 I/O 线程将主服务器的二进制日志读取过来记录到从服务器本地文件,然后 SQL 线程会读取 relay-log 日志的内容并应用到从服务器,从而
「使从服务器和主服务器的数据保持一致」
。
篇幅就不拉太长了,需要的朋友可以+V MXD202007
边栏推荐
- After Effects tutorial, How to adjust overexposed snapshots in After Effects?
- 无主复制系统(1)-节点故障时写DB
- Automated testing - web automation - first acquaintance with selenium
- 上传图片-微信小程序(那些年的坑记录2022.4)
- 你辛辛苦苦写的文章可能不是你的原创
- Mariabackup实现Mariadb 10.3的增量数据备份
- Handling write conflicts under multi-master replication (3) - Convergence to a consistent state and custom conflict resolution logic
- 21.支持向量机—核函数的介绍
- adb shell error error: device unauthorized
- ECCV 2022 华科&ETH提出首个用于伪装实例分割的一阶段Transformer的框架OSFormer!代码已开源!...
猜你喜欢
随机推荐
智能垃圾桶(八)——红外对管传感器(树莓派pico)
LevelSequence源码分析
adb shell 报错error: device unauthorized
浅谈网络安全之算法安全
【源码解析】BeanFactory和FactoryBean
How to switch remote server in gerrit
SHELL内外置命令
2022 Android interview summary (with interview questions | source code | interview materials)
牛客 HJ3 明明的随机数
基于C语言的编译器设计与实现
Flex布局详解
mysql的备份表的几种方法
牛客 HJ20 密码验证合格程序
Handling Write Conflicts under Multi-Master Replication (1)-Synchronous and Asynchronous Conflict Detection and Conflict Avoidance
关于柱状图的经典画法总结
[Network Communication 3] Advantech Gateway Modbus Service Settings
js的toString方法
Mariabackup implements incremental data backup for Mariadb 10.3
【愚公系列】2022年07月 Go教学课程 020-Go容器之数组
宁波大学NBU IT项目管理期末考试知识点整理









