前言
文本已收录至我的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 有我找的许多的材料送给大家