一条 SQL 查询语句是如何执行的?

连接器

  • 负责服务端与客户端建立连接,验证密码是否正确,是否有权限

分析器

  • 对要进行执行的 SQL 语句进行词法分析和语法解析

优化器

  • 决定使用哪个索引,还有类似 join 时刻表的连接顺序等

执行器

  • 真正执行这个 SQL 语句,如果没有权限会拦截掉

一条 Update 语句是怎么执行的?

执行顺序

  1. 执行器先去引擎中找到对应的行
  2. 找到对应的行之后进行计算处理
  3. 引擎将这部分数据记录到内存中,同时记录 redo log 状态为 prepare,告知执行器执行结束
  4. 执行器生成 binlog 写入磁盘
  5. 执行器调用引擎提交事务的接口,修改 redo log 的状态为 commit

什么是 redo log

  • 物理日志,InnoDB 特有。redo log 记录了对于哪个数据页进行修改,同时保证脏页能够及时回刷到磁盘中(两阶段提交)。有大小限制,写策略是循环写
  • 什么是脏页?
    • 内存中与磁盘数据不一致的部分
    • 在 InnoDB 中,数据的读取是按照页(page)进行,读取一行数据时候会将这行数据整页的方式进行读入

什么是 binlog

  • 逻辑日志,MySQL 的 server 层实现的,记录了每一行数据的执行逻辑,默认无大小限制,写策略是追加写

什么是两阶段提交

  • redo log 的两种状态,prepare 和 commit,保证宕机后数据可以正确恢复
  • 为什么两阶段提交可以保证数据可以被正确恢复?
    • 两阶段提交把是否提交成功变成了可重放、可判定的状态机,不依赖内存状态
    • 正确恢复主要有三件事:
      1. 已提交事务不丢失
      2. 未提交事务不生效
      3. 引擎存储数据和 binlog 一致(保证主从同步的数据一致性)
    • 两阶段提交的原理:
      1. 写 redo log prepare(落盘)
      2. 写 binlog 落盘
      3. 写 redo log commit 落盘
    • 崩溃恢复判定:
      • 如果崩溃发生在阶段 3:事务已经提交
      • 如果崩溃发生在阶段 2:事务可以提交
      • 如果崩溃发生在阶段 1:事务回滚
    • binlog 如果写入磁盘即可保证主从一致性,两阶段提交主要解决 redo log 以及 binlog 的一致性

为什么要有两份日志

  • redo log 和 binlog 的职能不同
  • redo log:给 InnoDB 自己用(本地崩溃恢复),主要解决的问题是内存数据没有回刷到磁盘的问题
  • binlog:给 MySQL 的 server 层使用,逻辑变更日志可以回放当时业务操作,由于是追加写入可长期保存归档
  • redo log 设计太底层,并且由于覆写限制无法实现归档/复制
  • binlog 是逻辑日志,无法处理引擎页级崩溃恢复设计,不能替代 redo 的快速本地恢复能力

关联