十、MySQL 日志

redo log

  MySQL 在执行增删改时会写入一条日志到 redo log 日志文件中,以保证事务提交后,修改的数据一定不会丢失。因为就算事务提交后,数据库宕机了,MySQL 也能根据 redo log 来恢复宕机前修改的数据,再把数据刷回磁盘。可是为什么不在宕机前直接把修改的数据刷回磁盘呢?因为缓存页刷盘实际上是一种随机写的操作,性能非常差。而写 redo log 是顺序写操作,性能很高。再就是一般 redo log 就几十个字节,而一个缓存页是 16 kb,光从写入大小就知道性能如何了。

redo log 数据结构

  redo log 记录的是 表空间号+数据页号+偏移量+修改几个字节的值+具体对的值 ,然后 redo log 根据修改的值分为几个类型:

  MLOG_1BYTE:修改一个字节
  MLOG_2BYTE:修改二个字节
  MLOG_4BYTE:修改四个字节
  MLOG_8BYTE:修改八个字节
  MLOG_WRITE_STRING:修改大字符串

  所以实际上 redo log 实际上是这样的:

日志类型(就是类似MLOG_1BYTE之类的),表空间ID,数据页号,数据页中的偏移量,具体修改的数据

   如果是 MLOG_WRITE_STRING 类型,那么还会记录一个修改数据长度

日志类型(MLOG_WRITE_STRING),表空间ID,数据页号,数据页中的偏移量,修改数据长度,具体修改的数据

redo log block

  MySQL 实际上对于 redo log 也有一个类似 buffer pool 和缓存页的数据结构,就是 redo log buffer 和 redo log block(简称 block)。MySQL 在启动时也会划分一块连续的内存给 redo log buffer,然后里面划分为一系列的 block(512 字节)。通过参数 innodb_log_buffer_size 指定 redo log buffer 大小,默认为 16MB。

  redo log block 结构如下:主要分为 header、body、trailer 三个部分。

  实际上,redo log 在写入磁盘之前会写入 block。通常一个事务会存在多个增删改操作,会对应多个 redo log,也就是一组 redo log。事务提交时,会把这一组 redo log 写入 block,如果一个 block 放不下,可能会存放到多个 block;反之,一个 block 可能存放多组 redo log。

  redo log 实际上会写入一个目录的文件中,通过命令 “show variables like 'datadir'” 来查看,可以使用参数 innodb_log_group_home_dir 来设置这个目录。目录下的 redo log 文件默认为 2 个,每个大小为 48MB,通过参数 innodb_log_files_in_group 可以指定文件数量。redo log 对这些文件顺序写入,写满之后会覆盖原来的文件日志,如此循环,所以 redo log 日志文件占用的空间最大就是设置的文件数 * 文件大小。

  redo log 写入 block 后,会选择一个时机刷入磁盘:

  1. redo log buffer 使用量超过一半(8M),此时会刷入磁盘。
  2. 事务提交时会把 redo log 所在的 block 刷入磁盘。(通过 innodb_flush_log_at_trx_commit 参数设置 redo log 刷盘策略)
  3. 定时线程,每隔 1 秒就会把 redo log buffer 中 block 刷入磁盘。
  4. MySQL 关闭时,block 会刷盘。

undo log

  MySQL 在执行增删改前不仅会写入记录本次操作的 redo log,还会记录操作时的 undo log,以便在事务回滚时可以恢复数据。undo log 的数据结构如下:

  主键:可能是自己指定的单列字段或者联合主键,即使没有设置主键也会使用 row_id 隐藏字段作为主键。

  列长度和列值:就是记录这条数据的每个列长度和值。

  日志类型:比如 insert 就是 TRX_UNDO_INSERT_REC。

  undo log 分为两类:

  insert undo log(包含 insert 操作),因为 insert 操作的记录只对事务本身可见,因此该 undo log 在事务提交后直接删除;
  update undo log(包含 update 和 delete 操作),记录的是 update 和 delete 操作产生的 undo log 日志,该日志在 mvcc 机制中作为版本链,因此不能在事务提交时删除,它会等待 purge 线程清理。

  undo log 是逻辑日志,记录了变更操作的反向操作,以 insert 语句为例,undo log 记录的就是回滚时的 delete 逻辑。

  innodb 通过 innodb_purge_threads 参数控制开启 purge 线程的数量;

  innodb_purge_batch_size 参数设置 purge 批量清除日志的数量;

  innodb_purge_rseg_truncate_frequency 参数设置 purge 清除回滚段的频率;

  其实,undo log 不仅仅用来作为事务回滚时恢复数据的,它也在 MySQL 事务隔离实现中作为 undo log 版本链。

posted @   维维尼~  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示