关于面试:2021Java后端工程师面试指南MySQL

31次阅读

共计 6901 个字符,预计需要花费 18 分钟才能阅读完成。

前言

文本已收录至我的 GitHub 仓库,欢送 Star:https://github.com/bin3923282…
种一棵树最好的工夫是十年前,其次是当初

Tips

面试指南系列,很多状况下不会去深挖细节,是小六六以被面试者的角色去回顾常识的一种形式,所以我默认大部分的货色,作为面试官的你,必定是懂的。

https://www.processon.com/vie…

下面的是脑图地址

叨絮

可能大家感觉有点陈词滥调了,的确也是。面试题,面试宝典,轻易一搜,基本看不完,也看不过去,那我写这个的意义又何在呢?其实嘛我写这个的有以下的目标

  • 第一就是通过一个体系的温习,让本人后面的写的文章再从新的过一遍,总结升华嘛
  • 第二就是通过写文章帮忙大家建设一个温习体系,我会将大部分会问的的知识点以点带面的模式给大家做一个导论

而后上面是后面的文章汇总

  • 2021-Java 后端工程师面试指南 -(引言)
  • 2021-Java 后端工程师面试指南 -(Java 根底篇)
  • 2021-Java 后端工程师面试指南 -(并发 - 多线程)
  • 2021-Java 后端工程师面试指南 -(JVM)

明天大家一起来温习温习 MySQL 吧

## 聊聊 MySql 的构造吧
大体来说,MySQL 能够分为 Server 层和存储引擎层两局部。

Server 层包含连接器、查问缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数外围服 务性能,以及所有的内置函数(如日期、工夫、数学和加密函数等),所有跨存储引擎的性能都 在这一层实现,比方存储过程、触发器、视图等。

而存储引擎层负责数据的存储和提取。其架构模式是插件式的,反对 InnoDB、MyISAM、Memory 等多个存储引擎。当初最罕用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成 为了默认存储引擎。

聊聊 InnoDB 和 MyISAM 的区别吧

  • 第一个也是最重要的一个 InnoDB 反对事务,MyISAM 不反对
  • 在 MySQL 中,表级锁有两种模式:表共享读锁,表独占写锁。也就是说对于 MyISAM 引擎的表,多个用户能够对同一个表发动读的申请,然而如果一个用户对表进行写操作,那么则会阻塞其余用户对这个表的读和写。InnoDB 引擎的表是通过索引项来加锁实现的,即只有通过索引条件检索数据的时候,InnoDB 才会应用行级锁,否则也会应用表级锁。
  • InnoDB 汇集索引,MyISAM 非汇集索引
  • 企业级生成环境强制用 InnoDB,所以上面的面试题都是基于 InnoDB。

说说一个查问 SQL 的执行过程

  • 连接器:首先必定和 mysql 建设连贯的过程
  • 查问缓存: 在 8 以前,mysql 会把雷同的 sql,缓存起来,然而因为发现效率不是那么好,8 之后删除了
  • 分析器: 如果没有命中查问缓存,就要开始真正执行语句了。首先,MySQL 须要晓得你要做什么,因而 须要对 SQL 语句做解析
  • 优化器:优化器是在表外面有多个索引的时候,决定应用哪个索引
  • 执行器:MySQL 通过分析器晓得了你要做什么,通过优化器晓得了该怎么做,于是就进入了执行器阶 段,开始执行语句
  • 返回数据给到客户端

说说一条 SQL 的插入流程

update T set c=c+1 where ID=2;

  • 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎间接用树搜寻找到这一行。如果 ID=2 这一行所在的数据页原本就在内存中,就间接返回给执行器;否则,须要先从磁盘读入内 存,而后再返回。
  • 执行器拿到引擎给的行数据,把这个值加上 1,比方原来是 N,当初就是 N+1,失去新的 一行数据,再调用引擎接口写入这行新数据。
  • 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 外面,此时 redo log 处于 prepare 状态。而后告知执行器执行实现了,随时能够提交事务
  • 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
  • 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状 态,更新实现。

说说 Buffer Pool 吧

  • 它是 mysql 一个十分重要的内存组件,因为是在内存中操作的,所以速度比拟快
  • 倡议设置正当的 buffer pool 的大小,如果大小在内存的百分 60 适合
  • 要明确的是 pool 的构造是一页一页的
  • 如果内存够大,能够多设计几个 pool

Buffer Pool 脏数据页到底为什么会脏

  • 是因为咱们新增 更新 删除操作的时候只是对内存进行操作,和对咱们 redo log 日志进行操作,所以呢就会有脏数据
  • 在 buffer pool 外面 有一个保护脏数据页的双向链表,用来明确哪个数据页须要刷
  • 而后还有就是 lru 链表,就是假如咱们的 pool 满了,那么咱们必定要把一些数据删除,就是 lru 算法了(基于冷热数据拆散的思维的 lru)

说说 InnoDB 页

InnoDB 是一个将表中的数据存储到磁盘上的存储引擎,所以即便关机后重启咱们的数据还是存在的。而真正解决数据的过程是产生在内存中的,所以须要把磁盘中的数据加载到内存中,如果是解决写入或批改申请的话,还须要把内存中的内容刷新到磁盘上。而咱们晓得读写磁盘的速度十分慢,和内存读写差了几个数量级,所以当咱们想从表中获取某些记录时,InnoDB 存储引擎须要一条一条的把记录从磁盘上读出来么?不,那样会慢死,InnoDB 采取的形式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的根本单位,InnoDB 中页的大小个别为 16 KB。也就是在个别状况下,一次起码从磁盘中读取 16KB 的内容到内存中,一次起码把内存中的 16KB 内容刷新到磁盘中。

说说 InnoDB 行格局是怎么样的

就是咱们 mysql 外面一行的数据,再 innodb 外面分为了 2 个局部

  • 一个是咱们原始的数据,实在的数据,也就是列的值
  • 还有一个额定的数据 一个是变长字段的列表,一个是 NUll 值,还有一个是记录头信息

聊聊整个磁盘的存储的构造

首先是 InnoDB 的页存储构造,咱们晓得最大的构造是表,表外面能够分为很多个区,每个区外面又有很多的页 多个不同的页组成的是一个双向链表,而每个页外面的数据行会按主键的大小组成一个单向链表,并且每 4 到 8 个数据组成一个槽,每个槽存储在 pageDirectoy 外面,当咱们要查问页的行数据的时候,能够先定位到页,而后用 2 分法定位到槽,而后遍历槽,来定位到以后行的数据。

## 聊聊索引吧
首先哈 索引的实质是什么呢?其实索引就是始终放慢磁盘查问速度的一些数据结构,因为咱们磁盘 i / o 的性能比较慢,索引能够放慢咱们的查问速度。
### 聊聊有哪些数据结构适宜做索引构造的,优缺点是什么

  • Hash 索引:hash 表,我置信大家都很相熟了,他的长处查问速度快,然而他不反对范畴查问,哈希表这种构造实用于只有等值查问的场景
  • 二叉树:如果数据多了,树高会很高,查问的老本就会随着树高的减少而减少。
  • B 树:B 树曾经是不错的一个索引构造了,然而他的子节点也存储数据,所以还是不能管制数高,因为树的高度,其实就是代表咱们的 io
  • B+ 树:其实很简略,咱们看一下下面的数据结构,最开始的 Hash 不反对范畴查问,二叉树树高很高,只有 B 树跟 B + 有的一比。B 树一个节点能够存储多个元素,绝对于齐全均衡二叉树整体的树高升高了,磁盘 IO 效率进步了。而 B + 树是 B 树的升级版,只是把非叶子节点冗余一下,这么做的益处是为了进步范畴查找的效率。

你能够说说 InnoDB 的索引模型吗?

  • 主键索引,在 InnoDB 里,主键索引也被称为聚簇索引
  • 一般索引,就是咱们个别的索引
  • 惟一索引,具体排他性的索引
  • 组合索,能够多个列的索引

说说怎么从磁盘上加载数据,也就是查问的执行形式

MySQL 的查问的执行形式大抵分为下边两种:

  • 应用全表扫描进行查问
  • 应用索引进行查问

    • 针对主键或惟一二级索引的等值查问
    • 针对一般二级索引的等值查问
    • 针对索引列的范畴查问
    • 间接扫描整个索引

    磁盘拜访形式的分类

    • const:通过主键或者惟一二级索引列与常数的等值比拟来定位一条记录
    • ref:对于某个蕴含多个索引列的二级索引来说,只有是最右边的间断索引列是与常数的等值比拟就可能采纳 ref 的拜访办法
    • range:相似于范畴查问的形式
    • index:这个是什么意思呢?就是比方咱们的 where 条件不合乎查问的索引,然而查问的条件在一个组合索引中,那咱们遍历索引数,比遍历数据数要快。
    • all: 最间接的查问执行形式就是全表扫描,对于 InnoDB 表来说也就是间接扫描聚簇索引.

    说说常见的 sql 须要留神到的点,也就是 sql 优化

    • 对查问进行优化,应尽量避免全表扫描,首先应思考在 where 及 order by 波及的列上建设索引。
    • 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃应用索引而进行全表扫描
    • 应尽量避免在 where 子句中应用!= 或 <> 操作符,否则将引擎放弃应用索引而进行全表扫描。
    • 尽量避免在 where 子句中应用 or 来连贯条件,否则将导致引擎放弃应用索引而进行全表扫描,如:
    • 应尽量避免在 where 子句中对字段进行函数操作,这将导致引擎放弃应用索引而进行全表扫描
    • 不要在 where 子句中的“=”右边进行函数、算术运算或其余表达式运算,否则零碎将可能无奈正确应用索引
    • 并不是所有索引对查问都无效,SQL 是依据表中数据来进行查问优化的,当索引列有大量数据反复时,SQL 查问可能不会去利用索引,如一表中有字段 sex,male、female 简直各一半,那么即便在 sex 上建了索引也对查问效率起不了作用。
    • 索引并不是越多越好,索引诚然能够进步相应的 select 的效率,但同时也升高了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎么建索引须要慎重考虑,视具体情况而定。一个表的索引数最好不要超过 6 个,若太多则应思考一些不常应用到的列上建的索引是否有必要
  • 任何中央都不要应用 select from t,用具体的字段列表代替“”,不要返回用不到的任何字段
  • 尽量避免大事务操作,进步零碎并发能力
  • 尽量避免向客户端返回大数据量,若数据量过大,应该思考相应需要是否正当。
  • 最左准则,是设计组合索引的准则。
  • 尽可能的应用 varchar/nvarchar 代替 char/nchar,因为首先变长字段存储空间小,能够节俭存储空间,其次对于查问来说,在一个绝对较小的字段内搜寻效率显然要高些。

说说 EXPLAIN 关键字吧

小六六筛选几个有参考价值的列来说说。

  • id 每个单查问都有,id 越大越先执行,id 雷同示意加载表的程序是从上到下。
  • type:这个字段就是咱们后面说的查问的分类了 重点关注
  • possible_keys 可能的索引
  • key 理论用到的索引 重点关注
  • key_len 理论应用的索引长度
  • rows 预估要读取的行数 重点关注
  • Extra 额定的信息 比方看是否用到回表 Using index, 或者是否用到了长期表之类的

    说说 count(字段) count(主键 id) count(1) count(*)

    • count(主键 id),InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加
  • count(1),InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。

    • count(字段),如果这个“字段”是定义为 not null 的话,一行行地从记录外面读出这个字段,判断不能为 null,按行累加;
    • count(),并不会把全副字段取出来,而是专门做了优化,不取值。count() 必定不是 null,按行累加
    • 依照效率排序的话,count(字段)<count(主键 id)<count(1)≈count(),所以我倡议你,尽量应用 count()。

    事务

说说 mysql 的事务吧

ACID 这个必定得背的

  • 原子性(A):事务是最小单位,不可再分
  • 一致性©:事务要求所有的 DML 语句操作的时候,必须保障同时胜利或者同时失败
  • 隔离性(I):事务 A 和事务 B 之间具备隔离性
  • 持久性(D):是事务的保障,事务终结的标记(内存的数据长久到硬盘文件中)

聊聊它的隔离级别吧

  • 读未提交 会产生脏读
  • 读已提交 会产生 不可反复读
  • 可反复读 会产生 幻读
  • 串行化,没有问题

说说 sping 默认的事务流传级别

  • Spring 中事务的默认实现应用的是 AOP,也就是代理的形式,如果大家在应用代码测试时,同一个 Service 类中的办法互相调用须要应用注入的对象来调用,不要间接应用 this. 办法名来调用,this. 办法名调用是对象外部办法调用,不会通过 Spring 代理,也就是事务不会起作用
  • REQUIRED(Spring 默认的事务流传类型),如果以后没有事务,则本人新建一个事务,如果以后存在事务,则退出这个事务,这个咱们个别用的最多
  • SUPPORTS 以后存在事务,则退出以后事务,如果以后没有事务,就以非事务办法执行
  • MANDATORY 以后存在事务,则退出以后事务,如果以后事务不存在,则抛出异样。
  • REQUIRES_NEW 创立一个新事务,如果存在以后事务,则挂起该事务。
  • NOT_SUPPORTED 始终以非事务形式执行, 如果以后存在事务,则挂起以后事务

说说 MVCC 呗,谈谈你本人的认识

  • 在 Mysql 的 InnoDB 引擎中就是指在已提交读 (READ COMMITTD) 和可反复读 (REPEATABLE READ) 这两种隔离级别下的事务对于 SELECT 操作会拜访版本链中的记录的过程。
  • 在 InnoDB 引擎表中,它的聚簇索引记录中有两个必要的暗藏列:trx_id 和 roll_pointer
  • mvcc 通过排它锁的模式来批改数据
  • 批改之前会把数据放到 undolog 日志,如果事务提交,那就条件到数据外面,如果事务回滚,则放弃这个事务链
  • 读已提交和可反复读的 MVcc 的区别就是 再这个事务级别下,一个事务操作外面每次查问都会生成一个新的视图,更新本人最小事务 id 和最大事务 id, 而后可反复读不会,它只会在事务开始的时候生成一个一致性视图。

Mysql 的主从架构聊聊

说说什么是 mysql 主从复制?

主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从数据库上,而后在从数据库上对这些日志进行从新执行,从而使从数据库和主数据库的数据保持一致。

那你聊聊主从复制的原理

  • MySql 主库在事务提交时会把数据变更作为事件记录在二进制日志 Binlog 中;
  • 主库推送二进制日志文件 Binlog 中的事件到从库的中继日志 Relay Log 中,之后从库依据中继日志重做数据变更操作,通过逻辑复制来达到主库和从库的数据一致性;
  • MySql 通过三个线程来实现主从库间的数据复制,其中 Binlog Dump 线程跑在主库上,I/ O 线程和 SQL 线程跑着从库上;
  • 当在从库上启动复制时,首先创立 I / O 线程连贯主库,主库随后创立 Binlog Dump 线程读取数据库事件并发送给 I / O 线程,I/ O 线程获取到事件数据后更新到从库的中继日志 Relay Log 中去,之后从库上的 SQL 线程读取中继日志 Relay Log 中更新的数据库事件并利用,如下图所示。

聊聊 Mysql 的分库分表吧

首先来说说分库分表的各种类型吧

  • 垂直分表:这个就是咱们说的把大表变成小表,也就是分字段
  • 程度分表,就是说咱们把数据分到多个表外面
  • 按月分表,也就是这些数据不会变了,而后按工夫分。查问的时候不能跨月查问
  • 分库的话,个别当初一个库就是一个服务(按业务分库),这样分,或者是多个库一个服务(按表分库)

说说罕用的分库分表中间件

  • mycat:阿里开源的,然而目前生态不那么好了,
  • Sharding Sphere 这个很好,交融了 Sharding-JDBC、Sharding-Proxy、Sharding-Sidecar 文档齐全
  • 其实分库分表你不必中间件本人也能做,就是他们也是代理的模式帮你去聚合查问,如果你有 5 个库,那你要查排序,是不是每个库都要查出来,最初总的合起来排序这样。分页这些都是,实现起来还是很麻烦
  • ShardingSphere-JDBC 在 Java 的 JDBC 层提供的额定服务。它应用客户端直连数据库,以 jar 包模式提供服务,无需额定部署和依赖,可了解为增强版的 JDBC 驱动,齐全兼容 JDBC 和各种 ORM 框架。
  • ShardingSphere-Proxy 是 Apache ShardingSphere 的第二个产品。它定位为透明化的数据库代理端,提供封装了数据库二进制协定的服务端版本,用于实现对异构语言的反对。

说说如何满足“逾越多个程度切分数据库,且分库根据与排序根据为不同属性,并须要进行分页”的查问需要

  • 服务层通过 uid 取模将数据分布到两个库下来之后,每个数据库都失去了全局视线,数据依照 time 部分排序之后因为不分明到底是哪种状况,所以必须每个库都返回 3 页数据
  • 业务折衷法 - 禁止跳页查问 用失常的办法获得第一页数据,并失去第一页记录的 time_max

完结

Mysql 就这些吧,也不是很全,分库分表有很多实战,然而咱们在公司用的 hbase, 所以对于这块波及没有那么多,接下来 Redis 吧

日常求赞

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是 真粉

创作不易,各位的反对和认可,就是我创作的最大能源,咱们下篇文章见

微信 搜 “ 六脉神剑的程序人生 ” 回复 888 有我找的许多的材料送给大家

正文完
 0