我们来看看一条更新语句在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
表a拥有一个字段id和一个字段value
我们来看看这条update语句在MySQL内部是如何执行的?
- 执行器通过引擎找到id=1这一行。如果id=1这一行的数据页在内存中,直接返回给执行器;如果不在,则要从磁盘读入内存,再返回给执行器;
- 执行器拿到id=1这一行数据,把value值加1,产生一行新的数据,调用引擎接口写入这行新的数据;
- 引擎将新的这行数据更新到内存中,同时将这个操作记录到redo log,此时redo log处于prepare状态;
- 执行器生成更新操作的binlog,并写入磁盘;
- 执行器调用引擎的事务提交接口,引擎将刚刚写入的redo log改成commit提交状态,更新完成。
2.小结
一条更新语句的执行过程,除了要经过连接池、查询缓存、解析器、优化器、执行器这几个模块之外,还涉及到两个非常重要的日志模块: binlog(归档日志)和redo log(重做日志)。
通过本文的讲解,希望您对MySQL的物理组成有更深入的认识。