存储引擎

很多文章都是间接开始介绍有哪些存储引擎,并没有去介绍存储引擎自身。那么到底什么是存储引擎?不晓得大家有没有想过,MySQL是如何存储咱们丢进去的数据的?

其实存储引擎也很简略,我认为就是一种存储解决方案,实现了新增数据、更新数据和建设索引等等性能。

有哪些已有的存储引擎能够让咱们抉择呢?

InnoDB、MyISAM、Memory、CSV、Archive、Blackhole、Merge、Federated、Example

品种很多,然而罕用的存储引擎目前就只有InnoDB和MyISAM,我也会着重来介绍这两种存储引擎。

InnoDB是目前应用最广的MySQL存储引擎,MySQL从5.5版本开始InnoDB就曾经是默认的存储引擎了。那你晓得为什么InnoDB被宽泛的应用呢?先把这个问题放一放,咱们先来理解一下InnoDB存储引擎的底层原理。

InnoDB的内存架构次要分为三大块,缓冲池(Buffer Pool)、重做缓冲池(Redo Log Buffer)和额定内存池

缓冲池

InnoDB为了做数据的长久化,会将数据存储到磁盘上。然而面对大量的申请时,CPU的处理速度和磁盘的IO速度之间差距太大,为了进步整体的效率, InnoDB引入了缓冲池

当有申请来查问数据时,如果缓存池中没有,就会去磁盘中查找,将匹配到的数据放入缓存池中。同样的,如果有申请来批改数据,MySQL并不会间接去批改磁盘,而是会批改曾经在缓冲池的页中的数据,而后再将数据刷回磁盘,这就是缓冲池的作用,减速读,减速写,缩小与磁盘的IO交互。

缓冲池说白了就是把磁盘中的数据丢到内存,那既然是内存就会存在没有内存空间能够调配的状况。所以缓冲池采纳了LRU算法,在缓冲池中没有闲暇的页时,来进行页的淘汰。然而采纳这种算法会带来一个问题叫做缓冲池净化

当你在进行批量扫描甚至全表扫描时,可能会将缓冲池中的热点页全副替换进来。这样以来可能会导致MySQL的性能断崖式降落。所以InnoDB对LRU做了一些优化,躲避了这个问题。

MySQL采纳日志后行,在真正写数据之前,会首先记录一个日志,叫Redo Log,会定期的应用CheckPoint技术将新的Redo Log刷入磁盘,这个前面会讲。

除了数据之外,外面还存储了索引页、Undo页、插入缓冲、自适应哈希索引、InnoDB锁信息和数据字典。上面选几个比拟重要的来简略聊一聊。

插入缓冲

插入缓冲针对的操作是更新或者插入,咱们思考最坏的状况,那就是须要更新的数据都不在缓冲池中。那么此时会有上面两种计划。

  1. 来一条数据就间接写入磁盘
  2. 等数据达到某个阈值(例如50条)才批量的写入磁盘

很显著,第二种计划要好一点,缩小了与磁盘IO的交互。

两次写

鉴于都聊到了插入缓冲,我就不得不须要提一嘴两次写,因为我认为这两个InnoDB的个性是相辅相成的。

插入缓冲进步了MySQL的性能,而两次写则在此基础上进步了数据的可靠性。咱们晓得,当数据还在缓冲池中的时候,当机器宕机了,产生了写生效,有Redo Log来进行复原。然而如果是在从缓冲池中将数据刷回磁盘的时候宕机了呢?

这种状况叫做局部写生效,此时重做日志就无奈解决问题。

图片来源于网络, 侵删

在刷脏页时,并不是间接刷入磁盘,而是copy到内存中的Doublewrite Buffer中,而后再拷贝至磁盘共享表空间(你能够就了解为磁盘)中,每次写入1M,等copy实现后,再将Doublewrite Buffer中的页写入磁盘文件。

有了两次写机制,即便在刷脏页时宕机了,在实例复原的时候也能够从共享表空间中找到Doublewrite Buffer的页正本,间接将其笼罩原来的数据页即可。

自适应哈希索引

自适应索引就跟JVM在运行过程中,会动静的把某些热点代码编译成Machine Code一样,InnoDB会监控对所有索引的查问,对热点拜访的页建设哈希索引,以此来晋升访问速度。

你可能屡次看到了一个关键字,接下来那咱们就来聊一下页是什么?


=

,是InnoDB中数据管理的最小单位。当咱们查问数据时,其是以页为单位,将磁盘中的数据加载到缓冲池中的。同理,更新数据也是以页为单位,将咱们对数据的批改刷回磁盘。每页的默认大小为16k,每页中蕴含了若干行的数据,页的构造如下图所示。

图片来源于网络, 侵删

不必太纠结每个区是干嘛的,咱们只须要晓得这样设计的益处在哪儿。每一页的数据,能够通过FileHeader中的上一下和下一页的数据,页与页之间能够造成双向链表。因为在理论的物理存储上,数据并不是间断存储的。你能够把他了解成G1的Region在内存中的散布。

而一页中所蕴含的行数据,行与行之间则造成了单向链表。咱们存入的行数据最终会到User Records中,当然最后User Records并不占据任何存储空间。随着咱们存入的数据越来越多,User Records会越来越大,Free Space的空间会越来越小,直到被占用完,就会申请新的数据页。

User Records中的数据,是依照主键id来进行排序的,当咱们依照主键来进行查找时,会沿着这个单向链表始终往后找,

重做日志缓冲

下面聊过,InnoDB中缓冲池中的页数据更新会先于磁盘数据更新的,InnoDB也会采纳日志后行(Write Ahead Log)策略来刷新数据,什么意思呢?当事务开始时,会先记录Redo Log到Redo Log Buffer中,而后再更新缓冲池页数据。

Redo Log Buffer中的数据会依照肯定的频率写到重做日志中去。被更改过的页就会被标记成脏页,InnoDB会依据CheckPoint机制来将脏页刷到磁盘。

日志

下面提到了Redo log,这一大节就专门来讲一讲日志,日志分为如下两个维度。

MySQL层面

InnoDB层面

MySQL日志

MySQL的日志能够分为谬误日志、二进制文件、查问日志和满查问日志。

  • 谬误日志 很好了解,就是服务运行过程中产生的严重错误日志。当咱们的数据库无奈启动时,就能够来这里看看具体不能启动的起因是什么
  • 二进制文件 它有另外一个名字你应该相熟,叫Binlog,其记录了对数据库所有的更改。
  • 查问日志 记录了来自客户端的所有语句
  • 慢查问日志 这里记录了所有响应工夫超过阈值的SQL语句,这个阈值咱们能够本人设置,参数为long_query_time,其默认值为10s,且默认是敞开的状态,须要手动的关上。

InnoDB日志

InnoDB日志就只有两种,Redo Log和Undo Log,

  • Redo Log 重做日志,用于记录事务操作的变动,且记录的是批改之后的值。不论事务是否提交都会记录下来。例如在更新数据时,会先将更新的记录写到Redo Log中,再更新缓存中页中的数据。而后依照设置的更新策略,将内存中的数据刷回磁盘。
  • Undo Log 记录的是记录的事务开始之前的一个版本,可用于事务失败之后产生的回滚。

Redo Log记录的是具体某个数据页上的批改,只能在以后Server应用,而Binlog能够了解为能够给其余类型的存储引擎应用。这也是Binlog的一个重要作用,那就是主从复制,另外一个作用是数据恢复

下面提到过,Binlog中记录了所有对数据库的批改,其记录日志有三种格局。别离是Statement、Row和MixedLevel。

  • Statement 记录所有会批改数据的SQL,其只会记录SQL,并不需要记录下这个SQL影响的所有行,缩小了日志量,进步了性能。然而因为只是记录执行语句,不能保障在Slave节点上可能正确执行,所以还须要额定的记录一些上下文信息
  • Row 只保留被批改的记录,与Statement只记录执行SQL来比拟,Row会产生大量的日志。然而Row不必记录上下文信息了,只须要关注被改成啥样就行。
  • MixedLevel 就是Statement和Row混合应用。

具体应用哪种日志,须要依据理论状况来决定。例如一条UPDATE语句更新了很多的数据,采纳Statement会更加节俭空间,然而绝对的,Row会更加的牢靠。

InnoDB和MyISAM的区别

因为MyISAM并不罕用,我也不打算去深究其底层的一些原理和实现。咱们在这里简略的比照一下这两个存储引擎的区别就好。咱们分点来一点点形容。

  • 事务 InnoDB反对事务、回滚、事务平安和奔溃复原。而MyISAM不反对,但查问的速度要比InnoDB更快
  • 主键 InnoDB规定,如果没有设置主键,就主动的生成一个6字节的主键,而MyISAM容许没有任何索引和主键的存在,索引就是行的地址
  • 外键 InnoDB反对外键,而MyISAM不反对
  • 表锁 InnoDB反对行锁表锁,而MyISAM只反对表锁
  • 全文索引 InnoDB不反对全文索引,然而能够用插件来实现相应的性能,而MyISAM是自身就反对全本索引
  • 行数 InnoDB获取行数时,须要扫全表。而MyISAM保留了以后表的总行数,间接读取即可。

所以,简略总结一下,MyISAM只实用于查问大于更新的场景,如果你的零碎查问的状况占绝大多数(例如报表零碎)就能够应用MyISAM来存储,除此之外,都倡议应用InnoDB。

End

因为工夫的起因,本文只是简略的聊了聊InnoDB的整体架构,并没有很深刻的去聊某些点。例如InnoDB是如何改良来解决缓冲池净化的,其算法具体是什么,checkpoint是如何工作的等等,只是做一个简略的理解,之后如果有工夫的话再细聊。

如果你感觉这篇文章对你有帮忙,还麻烦点个赞关个注分个享留个言

也能够微信搜寻公众号【SH的全栈笔记】,当然也能够间接扫描二维码关注

拜了个拜