我们来看看一条更新语句在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内部是如何执行的?

  1. 执行器通过引擎找到id=1这一行。如果id=1这一行的数据页在内存中,直接返回给执行器;如果不在,则要从磁盘读入内存,再返回给执行器;
  2. 执行器拿到id=1这一行数据,把value值加1,产生一行新的数据,调用引擎接口写入这行新的数据;
  3. 引擎将新的这行数据更新到内存中,同时将这个操作记录到redo log,此时redo log处于prepare状态;
  4. 执行器生成更新操作的binlog,并写入磁盘;
  5. 执行器调用引擎的事务提交接口,引擎将刚刚写入的redo log改成commit提交状态,更新完成。

2.小结

一条更新语句的执行过程,除了要经过连接池、查询缓存、解析器、优化器、执行器这几个模块之外,还涉及到两个非常重要的日志模块: binlog(归档日志)和redo log(重做日志)。
通过本文的讲解,希望您对MySQL的物理组成有更深入的认识。