Server 层
存储引擎层
总流程
查询语句
连接器
查询缓存
分析器
优化器
执行器
更新语句
redo log(节省的是随机写磁盘的 IO 消耗(转成顺序写))
InnoDB 引擎
物理日志
循环写
binlog
server层
逻辑日志
追加写入
两阶段提交
为了知道,mysql 中一条 sql 语句是如何执行的,先讲一下 mysql 的宏观分层以及如何执行查询语句.

MySQL 宏观上分为 Server 层 和 存储引擎层, MySQL 通过 server 层调用存储引擎层操作数据返回结果,Server 层又可以分为
连接器负责跟客户端建立连接、获取权限、维持和管理连接。
分析器先会做“词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。做完了这些识别以后,就要做“语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。
执行器会根据表的引擎定义,去使用这个引擎提供的接口。示例:
mysql> select * from T where ID=10;
比如我们这个例子中的表 T 中,ID 字段没有索引,那么执行器的执行流程是这样的:
至此,这个语句就执行完成了。
查询语句的那一套流程,更新语句也是同样会走一遍。与查询流程不一样的是,更新流程还涉及两个重要的日志模块,它们正是我们今天要讨论的主角:redo log(重做日志)和 binlog(归档日志)。
如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高。
当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面。
InnoDB 的 redo log 是固定大小的,满了时不能再执行新的更新。由参数 innodb_log_file_size 和 innodb_log_files_in_group 决定。

有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。
redo log 是 InnoDB 引擎特有的日志,而 Server 层也有自己的日志,称为 binlog(归档日志).这两种日志有以下三点不同。
执行器和 InnoDB 引擎在执行这个简单的 update 语句时的内部流程:

将 redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"。