共计 3877 个字符,预计需要花费 10 分钟才能阅读完成。
存储引擎
很多文章都是间接开始介绍有哪些存储引擎,并没有去介绍存储引擎自身。那么到底什么是存储引擎?不晓得大家有没有想过,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 锁信息和数据字典。上面选几个比拟重要的来简略聊一聊。
插入缓冲
插入缓冲针对的操作是更新或者插入,咱们思考最坏的状况,那就是须要更新的数据都不在缓冲池中。那么此时会有上面两种计划。
- 来一条数据就间接写入磁盘
- 等数据达到某个阈值(例如 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 的全栈笔记】,当然也能够间接扫描二维码关注
拜了个拜