InnoDB 存储引擎
- 执行器会负责与存储引擎交汇,完成sql语句在内存和磁盘间的数据更新操作
会负责下面所有操作
一图流
事务开启
- 一般来说,更新、删除这些操作是会开启事务的
优先从缓冲池中加载待更新数据
- InnoDB 存储引擎具有缓冲池 (Buffer Pool)
- 在更新操作时,需要先查询对应的记录是否存在,这一步会优先从缓冲池中获取数据
- 如果没有,则会从磁盘中加载对应的数据到缓冲池中,且加上独占锁
加载时是加载数据页
- 加载的是数据页,16kb
- 会将所查找的数据的那一页数据页加载进 buffer pool
- 如果要连续修改的时候,就不用再从磁盘中加载了
记录undo 日志
- 为了未来的事务回滚需要,要将更新操作前的数据值记录到 undo 日志中
更新缓冲池
- 将缓冲池中的数据进行修改,此时缓冲池中的数据与磁盘中的数据不同
- 即此时缓冲池中的数据为脏数据
写 redo log buffer
- 为了避免缓冲池中的数据因为宕机等缘故丢失,需要对之前对数据修改的操作进行记录,即进行 redo 日志记录
- redo 日志用于恢复由于宕机等缘故丢失的更新数据
- redo log buffer 是一块专门保存记录修改操作的 redo 日志的内存空间
- 此时的 redo 日志还保存在内存中,在宕机后会丢失
此时的数据丢失不要紧
- 磁盘的数据没修改过
- 只是加了条 undo 日志
- 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 的数据一致,如果不一致,则判定事务失败