MySQL最常用的存储引擎是innodb,我们今天就借助一条更新语句的执行,了解下innodb具体是如何处理的,深入理解下它的架构。

假设更新语句是这样的:

update user set name ='xxx' where id = 1;

这条SQL语句发送到MySQL上后,会经过SQL接口、解析器、优化器、执行器几个阶段,解析SQL、生成执行计划,再由执行器调用存储引擎执行这个执行计划。

如下图所示:

图1 MySQL底层架构

下面我们就跟随一条update语句,分析下innodb存储引擎的架构设计。

1、innodb最重要的组件:缓冲池(BufferPool)

innodb存储引擎中有一个非常重要的组件,就是缓冲池(BufferPool),这里面会缓冲很多数据,以便于以后操作数据的时候,可以直接操作内存,就不用访问磁盘了。

图2 innoDB重要组件缓冲池

innoDB执行上面那条更新语句的时候,会先看id = 1的这条语句是否在缓冲池中,如果不再就需要从磁盘加载到缓冲池来,而且还会对这条记录加独占锁。

锁相关的知识点,后面会有讲解,这里不是重点,就不展开了。

2、undo日志文件

接下来,准备更新id = 1的这条数据时,会先把id = 1和name原来的值写入到undo日志文件中去。

这么做的目的是什么?当然是方便回滚了。

MySQL增删改数据都是放在事务里执行的,如果事务提交失败了,就可以根据undo日志进行回滚。

图3 undo日志文件

把id = 1的那条要更新的数据加载到缓冲池,把要更新数据的旧值写入undo日志文件后,就可以开始更新这条记录了。

更新的时候,先更新缓冲池的数据。更新完后,缓冲池里的数据就变成:name = 'xxx'了,而此时磁盘上的数据还是name='zhangsan'。此时innoDB数据状态就变成这样了:

图4 更新缓冲池数据

3、redo日志文件

此时缓冲池和磁盘上的数据是不一致的,如果MySQL宕机了,怎么办?

此时MySQL宕机了,缓冲池里的数据肯定就丢失了。

这时候,就要引入一个新的组件:redo日志。

redo日志也是一个内存缓冲区,用来存放redo日志的,就是用来记录你对数据做了那些修改。

比如,id = 1这条记录,修改了name,redo日志可能就这样:id = 1, name = 'xxx'。

图5 redo日志

有了redo log,MySQL宕机后重启,就可以恢复更新后的数据。

但是,如果此时MySQL数据库宕机了,会怎样?

必然是缓冲池中修改过的数据,redo log buffer日志都会丢失。

但是,这也不要紧,因为你更新数据的事务没有提交,此时MySQL宕机了,事务就执行失败了,客户端会收到一个数据库异常,MySQL重启后磁盘上的数据还是原样子。

所以数据还是一致的。

另外,redo日志是innoDB特有的一个组件。

4、提交事务

上面的步骤完成之后,就要提交事务了,此时会把redo日志刷到磁盘上去。

刷盘策略可以通过innodb_flush_log_at_trx_commit来配置。

这个配置有几个选项:

0,提交事务的时候,不会把redo日志刷入磁盘;

1,默认值,提交事务的时候,会把redo刷入磁盘,只要事务提交成功,redo日志就比如进入磁盘了。

2,提交事务的时候,会把redo刷入os cache。操作系统会不定期把os cache里的数据刷到磁盘里去。

所以innodb_flush_log_at_trx_commit等于0或2的时候,redo日志都有事务提交成功,没写进磁盘的可能,缓冲池里更新后的数据也丢失了。此时MySQL重启,就无法根据redo恢复更新后的数据,就会出现数据不一致情况。

所以一般情况下,我们都会把innodb_flush_log_at_trx_commit配置为1。

图6 redo日志

5、binlog日志

其实MySQL中提交事务的时候,还会记录binlog。binlog是MySQL server自己的日志文件。

redo日志属于一种偏向于物理性质的重做日志,它里面记录的相当于是“对某某数据页的某某记录,做了某某修改”。

binlog叫做归档日志,它里面记录的是偏向于逻辑性的日志,类似于redis的aof日志。

我们提交事物的时候,除了把redo log日志写到磁盘,还会同时把对应的binlog日志写到磁盘文件中。

图7 binlog日志

与redo log日志一样,binlog日志有两种刷盘策略,相应的配置项为:sync_binlog。

0,默认值,提交事务的时候,会把binlog刷入os cache。

1,提交事务的时候,会把binlog写入磁盘。

所以,当sync_binlog设置为0的时候,如果机器宕机,binlog会有丢失的风险。设置为1的时候,即使机器宕机,binlog日志也不会丢失。

当我们把binlog日志写入磁盘后,接着就完成了最终的事务提交,最后会把本次更新对应的binlog日志文件名和这次更新的binlog日志在文件里的位置,都写入到redo log日志里去,同时在redo log日志文件里写入一个commit标记。

到此为止,一个事务提交才是完成了。

图8 binlog刷到磁盘

最后再补充一点,在redo日志中写入commit标识,其目的是保持redo log日志与binlog日志一致的。

也就是说,innoDB根据commit标识判定一个事务是否执行成功。如果在图8的5、6、7步,必须是三个步骤都执行成功了,才算提交了事务。假如执行其中某个步骤的时候,机器宕机了,会怎样?

这时候,因为redo日志里没有commit标识,所以会判定此次事务执行不成功,就不会出现数据不一致的情况。

6、后台线程把内存数据刷到磁盘

此时事务提交了,已经把缓冲池(BufferPool)中的数据更新了,磁盘里也有了redo日志和binlog日志,但这时候,磁盘上的数据还是旧的啊。

所以MySQL会有一个后台IO线程,会在某个时间,随机把缓冲池(BufferPool)中的数据刷到磁盘上去。

图9  innoDB执行更新语句时的完整流程

后台IO线程把缓冲池的数据刷到磁盘前,即使MySQL宕机,也没关系,因为机器重启后,会根据redo日志回复之前提交事务所作的修改。

7、总结

通过一次更新数据的流程,了解了innoDB存储引擎做了哪些工作。更新前记录undo日志,更新缓冲池(BufferPool)里的数据,记录redo log日志,binlog日志,每一步都有其专门的作用,innoDB通过这套复杂的架构设计,保证了数据更新的高性能和一致性。

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

通过一条语句的执行,深入理解innoDB的底层架构相关推荐

  1. go mysql 查询语句_01 MySQL-初识MySQL-查询语句的执行流程-Go语言中文社区

    MySQL的基础架构 我们通过一条查询语句来看看MySQL是如何执行的,同时通过这条语句的执行,了解MySQL的整体架构体系.mysql> select * from T where ID=1: ...

  2. mysql一条语句是如何被执行的——带你了解mysql语句执行内部顺序

    文章目录 写在前面 MySQL基本架构 超详细架构图 连接器 查询缓存 解析器 MySQL 8.0对Parser所做的改进 优化器 执行器 存储引擎 SQL语句执行时间分析 参考资料 写在前面 sel ...

  3. python导包顺序_2019-03-21 python导入包以及Python程序执行顺序理解

    http://codingpy.com/article/python-import-101/ https://segmentfault.com/a/1190000009842139 (一)Python ...

  4. for语句的执行过程_带你深入了解Java流程控制语句

    概述 在一个程序执行的过程中,程序的流程对运行结果有直接的影响的.只有在清楚每条语句的执行流程的前提下,才能通过控制语句的执行顺序来实现我们想要的结果. 顺序结构 程序中最简单.最基本的流程控制,没有 ...

  5. 深入理解Lock的底层实现原理

    lock的实现完全是由java写的,和操作系统或者是JVM虚拟机没有任何关系.整体来看Lock主要是通过两个东西来实现的分别是CAS和ASQ(AbstractQueuedSynchronizer).通 ...

  6. 一块GPU搞定ChatGPT;ML系统入坑指南;理解GPU底层架构

    1. 跑ChatGPT体量模型,从此只需一块GPU 在发展技术,让大模型掌握更多能力的同时,也有人在尝试降低AI所需的算力资源.最近,一种名为FlexGen的技术因为「一块RTX 3090跑ChatG ...

  7. shell中执行某条语句失败能不能重复执行_如何理解Mysql中的事务隔离级别?

    要说清楚Mysql中的事务隔离级别,我们先从事务的定义说起.事务,是一个或一组sql语句组成的一个执行单元,这个执行单元要么全部执行,要么全部不执行.整个单独单元作为一个不可分割的整体,如果单元中某条 ...

  8. mysql执行一条语句会加锁吗_一条简单的更新语句,MySQL是如何加锁的?

    看如下一条sql语句: # table T (id int, name varchar(20)) delete from T where id = 10: MySQL在执行的过程中,是如何加锁呢? 在 ...

  9. 解析MySQL基础架构及一条SQL语句的执行流程和流转

    前言 本篇文章分析SQL语句在MySQL中的执行流程,包括SQL的查询在MySQL内部会怎么流转,SQL语句的更新是怎么完成的.在分析之前我们一起看看MySQL的基础架构,知道了 MySQL由那些组件 ...

最新文章

  1. linux内核设备管理典型算法,linux内核物理存储空间管理有哪些常用算法
  2. 人人皆可大数据!SACC教你玩转阿里ODPS
  3. 中国锂电池行业发展机遇及营销策略前景研究报告2021-2027年版
  4. 用python制作网页要学哪些东西_python实战计划学习:做一个网页
  5. 以 vim 的方式来使用 chrome 浏览器(利用 vimium 插件)
  6. 如何实现模糊查询LIKE
  7. Spark内存管理(2)—— 统一内存管理
  8. Scratch里定义重复动作的方法
  9. windows环境的python的环境变量_win的环境变量配置(Python实例)
  10. Oracle P6培训系列:03设置用户设置
  11. 关于oneNote插件加载不显示的问题(NoteHighlight)
  12. linux下hg无法运行_linux下hg无法运行_Linux下Mercurial (hg)配置说明
  13. 夏至海报设计素材,都分享在这里了
  14. 微软Windows字体被诉侵权?我们来聊聊有关网站侵权被诉的那些事。
  15. H3CNE中静态路由实验
  16. Android使用adb截屏
  17. 基于pyagme用python做接小球游戏
  18. 共轭(conjugate)
  19. PDF格式分析(六十六) Text 文字——简单字体
  20. php留言板的简单编写

热门文章

  1. 计算机拼图形 比创意教案,拼图形比创意教学设计.doc
  2. linux supervisor
  3. linux 安装 php 5.2_Linux下安装PHP5.5
  4. px4 uavcan linux,PX4开发指南-12.2.2.UAVCAN固件升级
  5. uos命令_ubuntu、debian、uos的命令
  6. zookeeper 和 kafka 集群搭建
  7. libwacom9 : Depends: libwacom-common (= 2.2.0-1) but 1.12-1 is to be installed
  8. kvm迁移镜像启动报错(the CPU is incompatible with host CPU: Host CPU does not provide required features: fma)
  9. Python字符串之'\x00'与空串''的区别
  10. C/C++:Windows编程—Windows RPC 传递自定义数据类型、自定义数据类型数组、指针数组