A:原子性 - 都做 或者 都不做

C:一致性 - 使用事务完成 , 从一个一致性状态转移到另一个一致性状态

I : 隔离性 - 并发控制 下保证不可见性 数据库并发控制 - 隔离性 I

D: 持久性 - 提交即永久保存

事务有嵌套的特征

redo日志:重做日志 , 保证 原子性 和 持久性 - 没成功可以恢复

undo日志: 保证一致性 - 失败了可以回滚

redo 恢复提交事务修改的页数据

undo 回滚行记录

redo 使用重做日志缓冲 完成到重做日志文件的过渡

可以选择多个不同的时机刷新重做日志缓冲

  • 1 : 事务提交的时候 fsync 触发 - 默认策略
  • 0 : 每秒刷新一次
  • 2: 事务提交的时候写入文件系统缓存,不fsync

fsync的作用:

  • binlog: 记录数据库的变化的逻辑操作文件,是数据库层面的日志,记录的是SQL语句,主要用于数据库的复制和恢复
    • binlog 是事务提交的时候写入的
  • redo log: innodb 层面的日志,记录页数据的修改;
    • redo 日志 恢复的是物理页的数据,所以 redo 是幂等 (一个物理页不断写就是一个覆盖的过程);
    • redo log是不断的写入,写入基本单位是 512 字节,默认是一个扇区的大小,保证原子性
  • undo 日志是存储在 undo segment 里面的;记录的是逆向的SQL, 事务很多,所以 undo log 不是幂等的,只能依次记录

LSN : 日志序列号 , 使用 8字节存储,代表重做日志的字节总数

  • 当前LSN:当前逻辑的最新的LSN
  • 刷入到重做日志缓冲区的LSN
  • 刷入到磁盘的LSN - 如果需要恢复数据,从这里开始恢复

MVCC是依赖 undo log 实现的,即读取之前的版本的行版本信息,实现非锁定读取

WAL

现在描述一下日志写入的过程

commit logging 写入数据前,先记录日志文件

  • 先记录日志文件,提交 commit record
  • 再修改数据,提交 end record

如果存在 end record , 表示事务成功了

如果存在 commit record , 没有 end record : 使用 redo 日志重做到磁盘

如果不存在 commit record :使用 undo 日志 ,回滚状态

上面的过程保证了数据的持久性,但是在事务提交前,还是不允许修改数据,即使现在磁盘存在空闲,所以性能不是很好

如果允许在事务提交前将数据写入到磁盘呢? - Write Ahead Logging

对于已经写入的数据,如果失败了如何回滚? =》 undo log , 允许提前写入,那就必须存在回退机制

  • 复习 ACID (@2024-01-18)