上节我们最后说到,SQL 的执行计划是执行器组件调用存储引擎的接口来完成的。那我们可以理解为:MySQL 这个数据库管理系统是依靠存储引擎与存放数据的磁盘文件进行交互的。
那么 MySQL 有哪些存储引擎呢?
主要有 MyISAM、InnoDB、Memory等等。而现在互联网中,基本都是使用 InnoDB 存储引擎,所以接下来将简单地介绍 InnoDB 存储引擎里面的组件。
我们现在都知道了,数据库的数据是存放在磁盘文件中的。那么,我们每次对表的增删改查都是直接在磁盘文件里面操作吗?
答案:不是的!
因为磁盘文件的随机读写的性能是非常差的,如果所有操作都在磁盘中进行,那么就不会有高性能 MySQL 的说法了,MySQL 也不能支持高并发,也不会在互联网中如此的流行。
这时候要引入 InnoDB 存储引擎最重要的一个组件,就是缓冲池(Buffer Pool)
,它是一个非常重要的内存结构。它是内存里面的,凭借着内存非常高性能的读写,使得 MySQL 不再苦恼于性能比较低的磁盘随机读写了。
我们先复习一下 MySQL 接收请求的过程。
①、MySQL 的工作线程专门监听数据库连接池的连接,有连接就获取连接中的 SQL 语句。
②、然后将 SQL 语句交给 SQL 接口
去处理,SQL 接口 里会进行下面的一系列流程。
③、查询解析器
将 SQL 语句解析成 MySQL 能理解的东西。
④、接着 查询优化器
去为 SQL 语句制定一套最优的执行计划。
⑤、执行器
会根据执行计划去调用存储引擎的接口。
上面是上篇文章总结到的东西,那么存储引擎的接口是怎么进行增删改查的呢?
以更新操作为例,其他的同理。
首先,存储引擎会先判断更新 SQL 对应的数据行是否在 缓冲池(Buffer Pool)
里面。如果在的话就直接在 缓冲池(Buffer Pool)
里更新数据然后返回;如果不在,则从磁盘文件里读取数据到 缓冲池(Buffer Pool)
里,然后进行更新操作,最后再返回结果。
我们都知道,在事务中,事务提交前是可以随时回滚对数据的更新的。那么是依靠什么来做的呢?
依靠的是 undo 日志文件
。
undo 日志文件的使用原理:
更新数据为例:假如你更新某行 id=100 的数据,将字段 name 由原来的“张三”改为“李四”,那么此时会将 "id=10" 和 “name=张三” 这两个关键信息写入undo 日志文件中。当你事务提交前需要回滚,就会从 undo 日志文件
中找到这两个关键字,然后进行更新操作的回滚。
上面说到,所有的增删改查操作其实是在缓冲池里面进行的,所以其实对数据的修改并没有立刻落实到磁盘文件里面。
那么有一个问题:在缓冲池的脏数据刷回磁盘文件中前,MySQL 宕机了怎么办?
此时 InnoDB 存储引擎提供了一个非常重要的组件,就是 redo log buffer
组件,它也是内存里的一块缓冲区。
redo log buffer 的使用原理:
还是以上面的更新操作为例,当数据更新后,会记录下数据更新的的关键信息,对应的就是 redo 日志,然后写入 redo log buffer
里。
但是还是会有一个问题,上面说到,redo log buffer
也是在内存里的。那当 MySQL 宕机时,由于内存里的所有数据都会丢失,所以缓冲池的脏数据和 redo log buffer
的日志还是会全部丢失。这样会造成一种情况,客户端收到更新成功的信息了,但是最后数据库里头的数据还是没更新成功。
所以,redo log buffer还有一个刷盘策略,它由参数 innodb_flush_log_at_trx_commit 来控制。
通常我们将此参数的值设置为 1:即当事务提交时,会将 redo log buffer
里的 redo 日志
强制刷回到磁盘中。这样就不用担心,事务提交成功,但是更新数据可能会丢失的问题了。
即使在 缓冲池(Buffer Pool)
的脏数据刷回磁盘前, MySQL 宕机了,也不会丢失数据,因为 MySQL 重启时可以根据磁盘中的 redo 日志
恢复之前所有脏数据的更新。
我们都知道,redo log buffer
是 InnoDB 存储引擎的组件,而 MySQL 支持很多种存储引擎,那么 MySQL 在撇除存储引擎后,自己就没有记录一下关于数据更新的日志吗?
答案是有的!所以,我们下一讲会分析一下 MySQL Server 的 binlog 组件~
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8