看完了MySQL小册,我为什么强烈推荐?

本文有福利相送,做为我鸽了这么久的歉意。面试

朋友们我又回来了,距离上次发文应该过了一个月了,期间有不少我的的杂事,致使个人文章不能正常的更新,给你们说声抱歉。算法

从上周开始吧,我开始看我在掘金好久之前买的一本小册:《从根上理解Mysql是怎么运行的》,本着买了会一半的原则,它一直在个人掘金里面吃灰。sql

直到最近,看到一些Java交流群里MVCC这个名词在个人时间线上反复出现,我知道这是提示我去好好梳理一下Mysql相关的知识了。数据库

因而我花了一周的时间把这本小册从头至尾的好好看了一遍,有些章节可能反复看了四五遍,自认这本小册里的知识我搞懂了1/3,真的很惭愧,竟然还不到一半,由于这个号称从根上理解Mysql的小册涉及到了不少概念,短短一周真的很难所有梳理清楚。缓存

整体上来讲,是一本干货满满的性价比好书,从行文内容上也能够看出做者的功底,值得二刷三刷。(这本书貌似准备在机工出版了,已经说了半年了,估计就一个月以内了~)markdown

我不是来写软文,也不是搞推荐,很纯粹的分享一下最近看这本书的感觉,这本书很适合会CRUD但对Mysq不甚了解的同窗。数据结构

简单画一个导图给你们看一下这本书都讲了什么:并发

我将小册讲诉的全部内容分为七部分,接下来我将根据导图的各个部分说说个人见解。分布式

InnoDB

你们若是查看过这本小册的目录,能够发现其前四章都是关于一些基础内容的,好比启动Mysql-Server,使用Mysql-Client进行链接和更改字符集什么的,因此这部分我并无标在导图上,有一个大概了解就能够。高并发

在这些基础以后,就开始了小册第一个硬菜:InnoDB原理的探究

InnoDB做为咱们最经常使用的Mysql存储引擎,做者对它的笔墨也是最多的,由于只有它支持事务,支持锁,因此在这部分讲述的不少内容都和后面的部分相呼应。

做者从一条记录提及,给咱们娓娓道来了InnoDB内部的数据管理方式:

一条数据库表记录会以一种叫记录格式的方式存储,以5.7为例列举了MySQL中四种行格式的不一样组成结构及其特性。

记录格式说完以后,又要说说记录格式放在哪了?记录格式放在一个名为的数据结构上,MySQL中有不少不一样的页用以不一样的用处。

每一个页是16KB大小,MySQL在读取数据或者持久化数据的时候都是以页为基本单位,也就是说一次性最小会读取或持久化16KB数据。

每次须要写入数据时,都会向对应的数据页申请内存,直至填满以后会申请下一个页,若是是删除数据则会标记为删除,可是数据被删除并不会移除此页,而是被删除的数据组成一个垃圾链表,等待新的数据来将其覆盖

那么页说完了,页又从属于谁呢?这时又引入了表空间的概念。

一个表对应一个表空间文件(表名.ibd),这个表空间文件里就是实际存放了数据的文件,数据记录被页管理,页又被表空间管理,这是一个层层递进的从属关系。

可是由于用表空间直接管理页能够跨度太大(一个表空间对应全部表数据,可是一个页才16KB,数据稍微大一点,就是一个表空间对应上万甚至几十万的页),因此表空间里面又进行分层:区和组

64个页对应一个区(64*16=1MB),256个区又对应一个组(256MB),这样划分以后一个逻辑从属关系就变成了:记录->数据页->区->组->表空间

同时为了加快加载速度,几乎全部系统都会用到的缓存就被引入了-缓存池。

缓存池的引入大大提升了数据页查询的效率,毕竟磁盘IO太太太慢了,缓存池会在MySQL启动时申请一块内存做为数据页的缓存池(数据库优化的时候能够谈谈这个思路),同时根据算法来较好的控制缓存池里的数据(最常访问啊什么的,这块蛮复杂的)。

至此,InnoDB的基础原理部分基本就是结束了,这部分我看下来最复杂的就是表空间部分,由于涉及到诸如索引之类的东西,能够说表空间这节是整本小册最难的,我看小册评论区也都是如此想法。

索引

看小册的时候原本就是抱着看索引的想法去的,可是没想到索引的篇幅很短,只有两章:索引原理和索引用法。

其实看小册的时候,我通常都是对照着看的,看完做者写的再去网上看看别人写的,二者结合起来去理解。

索引这块也是如此,可是做者写的真是蛮通俗易懂的,索引就是在行记录的基础上进行主键排序,由于主键是有序的因此用主键做为节点构成一颗B+树,这颗B+树的叶子节点就是全部的记录,非叶子节点是一种名叫目录树的东西,能够理解为对叶子节点进行分组用的,由于是B+树,因此使用二分查找能够很快的查找到对应节点。

这种非叶子节点直接是行记录数据的索引被称为聚簇索引,这种索引会在InnoDB中自动生成,且由于它叶子节点是全部的记录,因此它也是很占空间的东西。

咱们手动进行生成的索引叫作二级索引/辅助索引,这种索引生成后也会构成一个B+树,可是此树叶子节点并不记录行数据,而是记录对应行数据的主键,当你用二级索引拿到主键后,还要用主键从新搜索一次数据,这个过程叫作回表

若是建立二级索引时指定了多个列,这种索引叫作覆盖索引

除了这些做者还顺带讲了MyISAM的索引,它没有聚簇索引都是二级索引,但二级索引和InnoDB的又有些不一样,MyISAM的索引中记录的不是主键而是行号,能够经过对行号直接找到对应数据,这样就少了一次回表过程。


懂了索引以后,再去看索引用法的注意事项就简单多了~,好比:

  1. 索引列的类型尽可能小(减小创建索引耗费的空间)
  2. 删除表中的重复和冗余索引(索引列只会用到一个索引)
  3. 数据库主键自增(避免主键无序,这样会频繁打乱B+树的节点,由于B+树依靠主键排序)
  4. where 条件尽可能索引字段的顺序和建立联合索引时字段顺序一致(由于覆盖索引建立是按照多个索引字段值从左到右进行排序的)
  5. 模糊匹配指定左前缀能够用到索引(由于索引值排序时是按照从左到右,因此若是左侧值指定了也能够用到索引缩小范围)

还有不少其余的注意事项,这块网上基本说的都够了,我这里再也不赘述,避嫌。

单表的访问方式

单表的访问方式,咋一听很难理解的一个名词,实际上是MySQL的设计者给不一样的查询设立了不一样的叫法,好比用主键查询速度很是快,这种叫const,意为常量级查询,复杂度能够忽略掉。

这些都是一些知道了解的东西,由于算是一种规定,同时这部分是Explain的铺垫,Explain会用到这里面的知识。

Explain

Explain的知识网上博客讲的也很清楚了,由于都是一些概念性的知识,我之前学MySQL的时候看的周阳的课,里面也有讲到Explain相关知识。

它主要是列出了一条查询语句都走了哪些索引,影响了多少行数,我的以为其实效用不大,由于一条SQL交给执行器去执行以后,会有优化器进行优化,优化过的SQL可能已经和原来你编写的不同了,须要了解优化器优化过程才能看懂这个。

这种状况你可使用optimizer_trace去查看SQL的执行过程来知道优化器都作了哪些事。

也能够用其余方式好比:show status like '%last_query_cost%'

这条语句能够查询上条查询语句使用了多少成本,在SQL优化器对一个语句进行优化时会尝试计算不一样方案花费了多少成本,最终使用最少成本的那个优化方案,我以为这种方式能够比较直观的对比本身编写的两个SQL的性能差距。

子查询优化

在优化器优化这块,小册主要讲了优化器进行优化的一些方案,不过主要讲的仍是子查询的优化方案。

事务

InnoDB基础,索引,事务和锁,能够说是看完这本小册必需要了解的四大块了。

事务里的概念不少,ACID就不说了,既然是讲原理的书,那做者的笔墨就主要用在MySQL用了什么方案来保证事务和事务的回滚

MySQL使用redo日志来记录事务执行中的语句,用undo日志记录语句执行前记录的值,同时每一个事务都有一个全局ID。

redo日志能够保证系统哪怕崩溃了,重启回来以后还能根据里面的日志恢复到原样,undo则能够保证须要回滚时有对应的记录,undo还有一个做用,就是用来作MVCC。

MVCC(Mutil-Version Concurrency Control)-多版本并发控制,它是MySQL中用来解决并发读写的问题的一种方案。

在高并发的程序中,数据库每每会同时开启多个事务,执行过程当中多个事务交替执行,这就可能会出现事务并发问题:脏写,脏读,不可重复读和幻读。

这里咱们再来复习一下这四个概念:

  1. 脏写:一个事务修改了另外一个未提交事务修改过的数据
  2. 脏读:一个事务读到了另外一个事务未提交修改过的数据
  3. 不可重复读:一个事务能读到此事务开启后其余事务提交修改的值
  4. 幻读:一个事务中两条一样的查询条件进行查询时,后读到的数据比前一次多

这四个问题均可以经过锁来解决,可是这样的话性能必然是会降低的,因此在MySQL中选择这样作:

脏写通常是由锁来完成的,也就是一个时间点只有一个事务对一条记录进行写,避免脏写。

脏读,不可重复读,幻读则能够由MVCC来控制,加强MySQL的并发性能,其原理是经过undo日志维护了一个版本链,版本链每一个版本上面都有一个事务id来标识这个版本是由哪一个事务修改的,当前事务进行查询时会根据当前事务id进行计算能够看到这个版本链上的哪些记录,从而去避免脏读,不可重复读和幻读。

网上有些解读MVCC的时候说这是版本链+乐观锁,看了小册以后我在网上翻到了MySQL中关于这块的源码,和小册上面讲诉的同样,是经过计算(或者说判断)来决定能看到哪一个版本,乐观锁通常是比较新值和旧值,实际状况和乐观锁不太相像。

事务这块看完以后,发现数据库常问的MVCC也没有那么神秘,能够说是一句话就能说清的事。并且后来我突然想起来seata这个分布式事务的AT模式,它的原理实现其实就和MySQL里面的事务原理几乎是同样的。

有了前面的铺垫以后,看锁这一章会简单许多,可是小册上面的锁这一章仅仅是介绍了锁的分类,也就是说日常MySQL在用锁的时候通常会用到哪些锁,他们分别有什么特性,并无去深刻的去分析两个事务同时修改一条记录的状况下锁是怎么作的。

可是并非说做者没写,而是写在公众号里面了,,,关注公众号以后能够去看有三篇加锁实战分析的文章。

锁其实能够经过两个维度来划分:粒度和特性。(固然这是我本身的理解)

  • 粒度:根据影响的范围能够分为行级和表级。
  • 特性:根据锁的特性能够分为独占或共享。

两个维度组合一下通常就是四种:行级独占锁、行级共享锁、表级独占锁和表级共享锁。

除了这几种锁的具体实现,还介绍了锁在内存中的结构,虽然我前面说了这章很重要,但我本身也没有太过于细看,由于都是概念性须要记忆的东西。

其实这章结合公众号的加锁实战分析的文章是比较好的,这章就像是锁实战的先行知识,否则你直接去看锁实战,各类概念一上来恐怕给人搞得头都大了。

小结

这篇文章给我写的很是尴尬,由于有不少想多写出来的知识又不能写(文章内容最多只能由30%知识来源于小册),因此我原本是想从逻辑上详细给你们讲讲这本小册的内容,可是又得避嫌(侵权啊,抄袭啊),最后就感受有点有始无终了(极力推荐查看个人导图)。

不过像高频率的一些知识点,我仍是写到的了,好比索引原理和事务原理(不过有点简化),大部分开发应该是都没有这个知识深度,若是能好好记忆下里面的内容,面试的时候其实能够往深了说,能把一点说深总比你说一堆浅显易懂的知识点来的有用。

整体来讲这本小册仍是比较推荐的,是一本深挖原理的书,有些知识点好比bin log这种偏应用层的没有讲到,其余的基本上都是很详细了,用一下小册优惠码应该不到20块钱,性价比很高。

文章开头也说了,本文有一点点福利,给你们抽三个小册六折码(非赞助,都是我以前参加征文活动攒的),鉴于上次抽奖的教训(由于没有私信,迟迟联系不上中奖者),此次打算转移到公号去抽奖。

  • 只需关注个人同名公众号(和耳朵),回复抽奖就有专属的抽奖链接,十月一日中午十二点开奖。
  • 还有个人MySQL思惟导图文件,回复MySQL关键字就能获取脑图。

好了,今天的文章就先到这,欢迎你们点赞支持,我是和耳朵,知识输出,共同成长。

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息