35. MySQL 物理组成-一条更新语句是如何执行的
上一小节,我们介绍了 MySQL 的日志文件和数据文件,相信大家对 MySQL 的物理组成已经有了一个初步认识。本小节,我们继续深入,来看看一条更新语句在 MySQL 内部是如何执行的?以及 binlog(归档日志)和 redo log(重做日志)在其中所起的重要作用。
1.一条更新语句是如何执行的
相比查询语句的执行流程,更新语句的执行流程多了两个重要的日志模块: binlog(归档日志)和 redo log(重做日志) 。上一小节,我们介绍了这两个日志的基本概念,大家可能会有疑问,这两份日志,到底有啥区别?为什么会有两份日志呢?
1.1 binlog 和 redo log 的区别
- binlog 是逻辑日志,记录某个语句的基本逻辑,即 SQL 语句;redo log 是物理日志,记录在某个数据页所做的修改;
- binlog 是在 MySQL 的 Server 层实现,所有的存储引擎都可以使用 binlog 这个日志模块;redo log 是 InnoDB 存储引擎特有的日志模块;
- binlog 是追加写,在写满或重启之后,会生成新的 binlog 文件,之前的日志不会进行覆盖;redo log 是循环写,空间大小是固定的;
- binlog 是在事务最终提交前写入的;redo log 是在事务执行过程不断的写入;
- binlog 可以应用于数据归档、主从搭建等场景;redo log 作为异常宕机或者介质故障后的数据恢复使用;
1.2 为什么会有两份日志
刚开始 MySQL 自带的引擎是 MyISAM,然而 MyISAM 并没有 crash-safe 的能力,而 binlog 只能用于数据归档。InnoDB 引擎是另外一家公司开发的 MySQL 插件,同时开发了 redo log 来实现 crash-safe 能力。从 5.5.5 版本开始,InnoDB 成为 MySQL 的默认存储引擎,也是当前最常用的存储引擎。
Tips:crash-safe 指数据库发生故障重启,之前提交的数据不会丢失。
1.3 一条更新语句的执行流程
update 语句将 id 等于 1 这一行的 value 值加 1。
update a set value=value+1 where id=1;
表 a 拥有一个字段 id 和一个字段 value:
CREATE TABLE `a` ( `id` int(11) DEFAULT NULL, `value` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8
我们来看看这条 update 语句在 MySQL 内部是如何执行的?
- 执行器通过引擎找到 id=1 这一行。如果 id=1 这一行的数据页在内存中,直接返回给执行器;如果不在,则要从磁盘读入内存,再返回给执行器;
- 执行器拿到 id=1 这一行数据,把 value 值加 1,产生一行新的数据,调用引擎接口写入这行新的数据;
- 引擎将新的这行数据更新到内存中,同时将这个操作记录到 redo log,此时 redo log 处于 prepare 状态;
- 执行器生成更新操作的 binlog,并写入磁盘;
- 执行器调用引擎的事务提交接口,引擎将刚刚写入的 redo log 改成 commit 提交状态,更新完成。
2.小结
一条更新语句的执行过程,除了要经过连接池、查询缓存、解析器、优化器、执行器这几个模块之外,还涉及到两个非常重要的日志模块: binlog(归档日志)和 redo log(重做日志)。
通过本文的讲解,希望您对 MySQL 的物理组成有更深入的认识。
码云笔记 » 35. MySQL 物理组成-一条更新语句是如何执行的