MySQL 到底是如何执行 SQL 语句的
写在前面
MySQL 是各大互联网公司使用最多的关系型数据库。由于其轻便、开源的特点,广泛应用。但我们在使用 MySQL 的时候,经常由于不清楚其工作原理,导致出现各式各样的问题。最为显著的就是慢 SQL。
MySQL 工作原理
慢 SQL 对于开发人员来说,是使用过程中最常见的问题。究其根本就是对于 MySQL 中 SQL 执行的计划不了解。所以我们必须要弄清楚 MySQL 语句的执行过程。
MySQL 执行原理图
对于 MySQL 语句执行的过程,大多数人熟悉的是如上图所示。主要是 MySQL 的 Server 层的工作流程,而对于 Server 层和存储引擎的交互却知之甚少。我今天详细介绍下执行器和存储引擎的交互(以 innoDB 引擎为例)。
MySQL InnoDB 引擎对数据的读写,并不是直接操作的磁盘,而是将结果读入内存,进行操作。这块内存空间叫做 InnoDB Buffer Pool。MySQL 是如何通过这块内存空间进行 Server 端和存储引擎交互的,分查询语句和更新语句分别进行解释下。
我们知道 MySQL 的数据储存单位是数据页,默认大小是 16K。
查询场景
MySQL 进行数据查询的时候,先查询 Buffer Pool,如果不存在对应数据页,则查询磁盘的数据页,并将相关的数据页加载到 Buffer Pool 中,然后在 Buffer Pool 中进行数据的筛查。
更新场景
MySQL 对数据更新的时候,还是查找 Buffer Pool 中的数据页,如果存在,直接更新内存。不存在,则从磁盘读取数据页到 Buffer Pool,再更新 Buffer Pool 中的数据页。然后,MySQL 会通过异步线程,每隔一段时间将 Buffer Pool 中的数据页批量刷新到磁盘中,这样大大减少了磁盘的 IO 操作,节省了很多时间。
可能有同学问,数据在 Buffer Pool 和磁盘各存储一份。万一,在 Buffer Pool 同步到磁盘之前,数据库宕机,那 Buffer Pool 中的数据岂不丢失了?MySQL 为保证已提交的事务的数据持久性,引入了 redo log,redo log 是 InnoDB 引擎特有的机制。有了 redo log,更新语句修改完 Buffer Pool 中的数据页后,redo log 会进行记录。这样就能保证数据库宕机后,仍然能从 redo log 中恢复数据。
我们知道 redo log 是存储在磁盘上的日志文件,MySQL 就是为了减少和磁盘的交互,才引入 Buffer Pool,让操作在内存中进行。但这时又引入 redo log 进行磁盘操作,意义何在?这是因为数据页存储在磁盘中,但操作的具体内容并不受 MySQL 控制,一些数据页的操作属于随机读写范畴。而 redo log 是对于磁盘操作是顺序读写的,这大大提高了性能(顺序读也是 kafka,rocketMQ 吞吐量高的原因之一)。
总结
其实在应用开发过程中,MySQL 这样保证数据最终一致性的实现方案,我们也可以参考实现。
版权声明: 本文为 InfoQ 作者【技术小生】的原创文章。
原文链接:【http://xie.infoq.cn/article/c214e898260dd039eade1ed59】。文章转载请联系作者。
评论