查询
select * from T where id = 1;
执行流程
流程说明
- 在查询之前,需要去连接数据库,这时候MYSQL会校验用户名和密码,如过不正确则直接返回,如果校验通过则拉取该用户的权限信息,并缓存在连接中
- 获取连接后,先去缓存中查看是否该语句是否存在结果缓存,如果存在,则校验是否有权限,如果有则返回结果,否则返回无权限
- 缓存中无数据,分析器对SQL进行词法和语法分析,解析出这个SQL要做什么(例子中的SQL解析结果为去T表中查询id为1的数据)
- 优化器生成执行计划,以最优的方式让执行器执行SQL语句
- 执行器判断是否有查询该表的权限,如果有则调用对应的存储引擎的接口进行查询操作
- 返回结果前,将数据放入缓存中,返回结果到客户端
更新
在讨论更新之前,先要讲两个知识点:
- 存储引擎在底层对数据进行操作的时候也是分冷热的,即热数据是在内存中的
- 更新时,会涉及到MYSQL的两个重要的日志模块——binlog和redo log,可点击链接查看相关资料。
update T set field = 'new' where id = 1;
执行流程
流程说明
- 首先先看看缓存中是否有本次更新表的缓存数据,如果存在则失效
- 进行词法语法分析
- 优化器生成执行计划
- 查看是否有更新权限,如果没有,则返回无权限
- 执行器调用存储引擎,查询符合where条件的数据
- 存储引擎查看内存中是否存在该数据,如果存在,则直接返回,如果不存在,则去磁盘中加载到内存再返回
- 执行器拿到存储引擎返回的数据行,对数据进行更新操作
- 存储引擎将内存中的数据进行更新,并写入redo log(此时redo log处于prepare阶段,如果binlog写失败,该日志为无效)
- 执行器将本次操作写入binlog
- 修改redo log为commit,提交事务
从上面的流程可以看出,最后在写binlog和redo log的时候比较绕,这里使用两阶段提交,为的就是确保两个日志都写成功或者都没有成功,防止出现不一致。
因为redo log支持prepare和commit,所以先让存储引擎写redo log,并处于prepare状态,如果后面的步骤都成功,则提交事务,redo log也是写入成功的,如果后面写binlog过程中出现异常,那么redo log也不会提交,也是无效的。