82-log

1. sql入库流程

Image
  1. 执行器先从Engine中找数据。如果没有,查询DB写入Buffer_Pool
  2. 执行器执行sql,同时记录redo_log, undo_log,此时处于prepare阶段。再通知执行器执行完成
  3. 执行器记录bin_log,并调用Engine进行commit
  4. disk更新。redo_log, undo_log刷到OS_cache

2. Buffer_Pool

image-20230325211445003
  1. 缓存MySQL磁盘数据的内存空间
  2. 内存操作,快
  3. Buffer_Pool减少Disk_IO
# 事务A
update user set age = 2

# 事务B
update user set age = 3

# 事务C
update user set age = 4
Image
Image

问题:断电了,数据一致性?=>(redo_log)

3. redo_log(前滚日志)

  1. Aim:保证Trx持久性。恢复Buffer_Pool
    • InnoDB就可以保证即使DB发生异常重启,之前的记录也不会丢失,叫做crash-safe
  2. 所属InnoDB引擎,物理日志
  3. redo_log是磁盘顺序写。WAL(Write-ahead logging),预写式日志,数据刷盘是磁盘随机写,磁盘的顺序写比随机写高效的多
    • redo_log固定大小,是循环写的过程。即先记下来,抽空异步写到磁盘日志文件上
  4. 磁盘顺序写进一步提高效率,引入redo_log_buffer
Image

加深理解

酒店的客人赊账账本。一天的流水先记录到小黑板上,夜里没人了再更新到账本上。

image-20220603202001376

1. Mysql挂了

  1. OS挂了。MySQL服务端是一个进程。Buffer_Pool、OS_cache数据全丢失
  2. OS没挂。Buffer_Pool数据丢失,OS_cache数据没丢失

2. redo_log落盘机制

# 0. 延迟写,延迟刷
innodb_flush_log_at_trx_commit = 0

# 1. 实时写,实时刷
innodb_flush_log_at_trx_commit = 1

# 2. 实时写,延迟刷。减少data在buffer_copy
innodb_flush_log_at_trx_commit = 2
image-20220603202011803

1. 延迟写,延迟刷

  1. 事务提交时,只会把数据写到redo_log_buffer,让后台线程定时去将redo_log_buffer里面的数据刷到disk
  2. 效率最高,风险最高
Image

2. 实时写,实时刷

  1. 事务提交之前,每次都会将数据从redo_log刷到磁盘中去
  2. 效率最低,风险最低
Image

3. 实时写,延迟刷

  1. commit,redo_log写到OS_cache,每秒执行一次刷新磁盘操作
  2. Mysql进程挂了,OS没挂,数据完好
  3. 效率比较高,风险比较低

4. undo_log(回滚日志)

  1. Aim
    1. 保证Trx原子性(回滚)
    2. InnoDB存储引擎中,还用undo_log来实现多版本并发控制(MVCC)
  2. 所属InnoDB引擎,逻辑日志
    1. delete一条记录,undo_log中会记录一条对应的insert记录
    2. insert一条记录,undo_log中会记录一条对应的delete记录
    3. update一条记录,记录一条对应相反的update记录
  3. undo_log默认存全局表空间,理解为插入一条undo_log和插入一条普通数据类似。写undo_log同样也要写入redo_log
Image

5. bin_log(二进制日志)

  1. Aim
    1. 提供了崩溃恢复的能力
    2. MySQL高可用(主从复制)依赖binlog复制
  2. 所属mysql_server,逻辑日志,记录所有的逻辑
  3. 恢复数据的过程
    1. 找到最近一次的全量备份数据
    2. 从备份的时间点开始,将备份的binlog取出来,重放到要恢复的那个时刻
image-20220603202051038

1. 落盘策略

# 每次提交事务前,将binlog写入OS_cache,由OS控制什么时候刷到磁盘
sync_binlog = 0

# 采用同步写磁盘的方式来写binlog,不使用OS_cache来写binlog
sync_binlog =1

# n次事务提交之后,调用一次fsync将OS_cache中的binlog强制刷到磁盘
sync_binlog = N

2. 区别redo_log

  1. binlog是Server层的日志。所有Engine都具备
    • redo_log是InnoDB的日志。如果不使用InnoDB引擎,则没有redo_log
  2. binlog是逻辑日志,记录的是对哪一个表的哪一行做了什么修改(sql记录)
    • redo_log是物理日志,记录的是对哪个数据页中的哪个记录做了什么修改,可以理解成对磁盘上的哪个地址的内容做了修改
  3. binlog是追加写
    • redo_log是循环写,日志文件有固定大小,会覆盖之前的数据

3. 取代bin_log

  1. binlog的生态已经建立。MySQL高可用依赖binlog复制
  2. binlog不是MySQL的瓶颈,花时间在没有瓶颈的地方没必要

6. 总图

Image