MySQL server层与存储引擎 执行查询语句流程
- 建立连接,获取权限(获取长连接后更新用户权限,此时长连接权限不会刷新)。(连接器)
- 查询缓存,若未命中,则执行分析器(语法,词法分析),命中直接返回。mysql8.0已删除查询缓存。
- 进入优化器(执行计划生成,索引选择)。
- 进入执行器(执行引擎,返回结果)。
- 在存储引擎中执行查询(存储引擎提供读写接口)。
执行更新语句流程
- 建立连接
- 执行分析器
- 执行优化器
- 进入执行器
- 执行引擎
当然,要了解更新语句的完整流程,我们还需要了解redo log和binlog,即mysql的日志系统。
redo log
mysql在执行更新语句时,不会直接将数据写入磁盘。而是先写入redo log(内存),再由innoDB引擎在适当的时候写入磁盘。这样能提升更新效率。 innoDB的redo log大小是固定的,那么当内存满了时,则需要innoDB先完成一部分写入磁盘操作,获得部分空闲内存后,再写入内存。 因此redo log需要write pos和checkpoint两个标记来标识当前写入位置与当前擦除位置,当write pos追上checkpoint,则将数据写入磁盘,将内存写入磁盘。
有了redo log,InnoDB就可以保证数据库发生异常重启,之前提交的数据也不会丢失,这就是InnoDB的crash-safe。
binlog
redo log数据innoDB引擎,即mysql引擎层。而binlog处于mysql的server层,又叫归档日志。 binlog没有crash-safe能力。 redo log与binlog的区别主要在于以下三点:
- redo log时innoDB引擎特有的,binlog是Server层实现的,所有的引擎都可以用。
- redo log是物理日志,存储数据页的修改记录。binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给表T中ID为2的字段C加1”。
- redo log是循环写,空间固定会用完,会擦除写入磁盘的记录。binlog是可以追加写的。
执行update语句的完整流程。
update T set c=c+1 where ID=2
- 执行器找引擎取ID=2这一行。ID是主键,引擎直接用数搜索找到这一行。如果ID=2这一行所在的数据页本来就在内存中,就直接返回给执行器。否则,引擎先从磁盘中读入数据,再返回给执行器。
- 执行器拿到引擎给的行数据,把这个值加上1,得到新的一行数据,再调用引擎接口写入。
- 引擎将这行数据更新至内存中,同时将更新操作记录到redo log中,此时redo log处于prepare状态,然后告知执行器执行完成,随时可以提交事务。
- 执行器生成这个操作的binlog,并将binlog写入磁盘。
- 执行器调用引擎的事务提交接口,引擎将刚写入的redo log改为commit状态。更新完成。