6.1一条sql语句执行流程
(1)首先经过连接管理模块,由连接进程模块从线程池分配一个执行线程来执行本次请求。请求转发到用户模块进行权限校验;
(2)然后由命令分发器进行分发,若是查询请求,先走查询缓存,看看是否命中,若命中,那么直接返回,记录日志,否则交给命令解析器执行。
(3)命令解析器根据传过来的sql判断类型交给对应模块。例如查询优化器,表变更模块,表维护模块,复制模块,状态模块。
(4)然后交给访问控制模块
(5)交给执行引擎,与存储引擎打交道,返回结果。
6.2 一条update语句的执行过程
update t set c = c + 1 where id = 2;
(1)执行器首先找到innodb存储引擎取id=2这一行记录。id是主键,引擎直接用数搜索到这一行。先看内存中是否存在对应数据页,若在就返回执行器。否则,需要从磁盘读取到内存,然后返回。
(2)执行器拿到引擎给的行记录,将值+1,得到新的一行记录,再调用存储引擎接口写入这行数据。
(3)引擎将这行数据更新到内存,同时将这个更新记录到redo log里面,此时redo log处于prepare状态,然后告知执行器执行完了,随时可以提交事务。
(4)执行器生成这个操作的binlog日志,并将binlog写入磁盘。
(5)执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交commit状态,更新完成。
我们看到prepare状态和commit状态,两阶段提交,先写binlog,然后再写redo log,防止数据库异常奔溃后通过日志恢复出来的库的状态不一致情况。
redo log可以保证crash-safe能力,innodb_flush_log_at_trx_commit=1表示每次事务的redo log都直接持久化到磁盘。sync_binlog=1表示每次事务的binlog都持久化到磁盘。