InnoDB 存储引擎

  • 执行器会负责与存储引擎交汇,完成sql语句在内存和磁盘间的数据更新操作
  • 会负责下面所有操作

    • 从磁盘加载数据到 buffer pool 中
    • 写 undo 日志
    • 更新 buffer pool
    • 写 redo 日志到 redo log buffer 中
    • redo 日志 刷入磁盘/不刷磁盘/刷os cache
    • 写 binlog
    • .etc

      更新操作步骤

  • 一图流

image.png

事务开启

  • 一般来说,更新、删除这些操作是会开启事务的

优先从缓冲池中加载待更新数据

  • InnoDB 存储引擎具有缓冲池 (Buffer Pool)
  • 在更新操作时,需要先查询对应的记录是否存在,这一步会优先从缓冲池中获取数据
    • 如果没有,则会从磁盘中加载对应的数据到缓冲池中,且加上独占锁

**

加载时是加载数据页

  • 加载的是数据页,16kb
  • 会将所查找的数据的那一页数据页加载进 buffer pool
  • 如果要连续修改的时候,就不用再从磁盘中加载了

记录undo 日志

  • 为了未来的事务回滚需要,要将更新操作前的数据值记录到 undo 日志中

更新缓冲池

  • 将缓冲池中的数据进行修改,此时缓冲池中的数据与磁盘中的数据不同
    • 即此时缓冲池中的数据为脏数据

写 redo log buffer

  • 为了避免缓冲池中的数据因为宕机等缘故丢失,需要对之前对数据修改的操作进行记录,即进行 redo 日志记录
    • redo 日志用于恢复由于宕机等缘故丢失的更新数据
  • redo log buffer 是一块专门保存记录修改操作的 redo 日志的内存空间
  • 此时的 redo 日志还保存在内存中,在宕机后会丢失

此时的数据丢失不要紧

  1. 磁盘的数据没修改过
  2. 只是加了条 undo 日志
  3. buffer pool 中更新的数据和 redo log buffer 中的 redo 日志是针对新数据的

那么此时 mysql 宕机,顶多会报个事务异常无法修改,但是原来的值并不会被改变

事务提交

  • 更新操作完成,假设此时需要提交事务,那么就会根据一定的策略把redo日志从redo log buffer 里刷入到磁盘文件里去。

    redo 刷盘策略

  • 策略是通过innodb_flush_log_at_trx_commit 来配置

    • 配置为 0 : 事务提交不会将 redo log buffer 中的 redo 日志刷到磁盘中
      • 如果此时 mysql 宕机,那么 buffer pool 和 redo log buffer 中的数据和 redo 日志都会丢失
      • 相当于事务内的操作都没干过
    • 配置为 1 : 事务提交将 redo log buffer 中的 redo 日志刷到磁盘中 推荐使用
      • 如果此时 mysql 宕机,那么 buffer pool 和 redo log buffer 中的数据和 redo 日志都会丢失
      • 但是由于磁盘中有了最新的 redo 日志,那么在恢复时就会按照 redo 记录重新在 buffer pool 保留更新后的数据
    • 配置为 2 : 事务提交将 redo log buffer 中的 redo 日志刷到磁盘文件对应 os cache 中
      • 如果此时 mysql 宕机,那么 buffer pool 和 redo log buffer 中的数据和 redo 日志都会丢失
      • 但是 os cache 中有最新的 redo 日志,那么在恢复时会按照 热动记录重新在 buffer pool 中保留更新后的数据
      • 但是此时 机器 宕机,那么 os cache 中的 redo 日志就会丢失,无法恢复
        • 相当于事务内的操作都没干过

事务提交的时候也会写入 binlog

  • 上面的 redo log,是偏向物理性质的重做日志,记录类似对数据也的啥记录做了啥修改
  • 而 binlog 是偏向逻辑性的日志,描述更为具体的内容,记录类似对啥表的哪个字段做了哪种性质的操作,变更为啥值
  • binlog 是 mysql server 自己的日志
  • 在事务提交的时候,不仅会将 redo log buffer 刷入磁盘/不刷入/刷入os cache(看 innodb_flush_log_at_trx_commit 如何设置),还会将 binlog 日志写入磁盘中
  • 可以说刷 redo 和写 binlog 是事务阶段

**

binlog 刷盘策略

  • 有参数 sync_binlog
    • 默认 0,事务提交时,binlog 是刷到 os cache 中的。
      • 机器宕机,会丢失
    • 1, 事务提交时, binlog 刷到磁盘中
      • 机器宕机,不会丢失

最终事务提交

  • 当完成 redo log 的刷盘,binlog 的刷盘后
    • 会将 binlog 的名称和位于磁盘中的位置写入 redo log 中,且写入一个 commit 标识
    • 这样才完成最终的事务提交

commit 标识的意义

  • 保证 redo log 和 binlog 的数据一致,如果不一致,则判定事务失败

后台IO线程随机将 buffer pool 的脏数据刷回磁盘

  • mysql 有个后台io线程,在某个时机将 buffer pool 的脏数据刷会磁盘

    也是通过数据页的方式刷回磁盘