MySQL 中的 7 种日志介绍

发布于 2022-09-26 13:04:48 字数 9409 浏览 159 评论 0

7 种日志文件:

  1. 重做日志(redo log)
  2. 回滚日志(undo log)
  3. 二进制日志(bin log)
  4. 错误日志(error log)
  5. 慢查询日志(slow query log)
  6. 一般查询日志(general log)
  7. 中继日志(relay log)

事务的4大特性 ACID。

一个很好的事务处理系统,必须具备这些标准特性:

  • 原子性(Atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。
  • 一致性(consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态。(其实原子性和隔离性间接的保证了一致性)
  • 隔离性(isolation):通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。
  • 持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。

重做日志(redo log)

利用WAL技术(Write-Ahead-Logging, 即先写日志,后写磁盘)推迟物理数据页的刷新,从而提升数据库吞吐,有效降低了访问时延。

redo log是InnoDB引擎特有的:binlog是MySQL的Service层实现的,所有的引擎都可以使用

redo log提供了crash-safe的能力,即使MySQL异常重启,之前提交的记录也不会丢失。

redo log是物理日志,记录的是在某一个数据页面上做了什么修改,binlog是逻辑日志,记录的是这个语句的原始逻辑

redo log是固定大小的,从头开始写,写到末尾之后又回头开头循环写,binlog是可以追加写当到达一定大小后会切换到下一个不会覆盖之前的日志

redo log的写入分成了 prepare 和 commit 两个阶段, 称为两阶段提交

redo log并不是直接写入磁盘的,而是先写入到缓存区,我们把这个缓冲区叫做 redo日志缓冲区

在 MySQL Server 5.7 下 redo日志缓冲区的大小默认为 1M,我们可以通过 innodb_log_buffer_size 参数来设置 redo 日志缓冲区的大小。

缓冲区和磁盘之间的数据如何同步?

在 MySQL配置文件中提供了 innodb_flush_log_at_trx_commit 参数,这个可以用来控制缓冲区和磁盘之间的数据如何同步:

  • 0:表示当提交事务时,并不将缓冲区的 redo 日志写入磁盘的日志文件,而是等待主线程每秒刷新。
  • 1:在事务提交时将缓冲区的 redo 日志同步写入到磁盘,保证一定会写入成功。
  • 2:在事务提交时将缓冲区的 redo 日志异步写入到磁盘,即不能完全保证 commit 时肯定会写入 redo 日志文件,只是有这个动作。

我们使用默认值 1 就好,这样可以保证 MySQL 异常重启之后数据不丢失。

InnoDb 引擎会先将操作(更新)记录写到 redo log 中,并更新内存,此时就算更新完成了。InnoDb 引擎会在空闲或适当的时候将操作记录写到磁盘上

  1. 上图中画出了序号从0-3,共4个redo log
  2. write pos为当前写入位置, check point为检查点, write pos和check point都一直向前推进;write pos和check point之间的绿色部分就可以用来写入redo log
  3. checkpoint之前的所有数据都已经刷新回磁盘,当DB crash后,通过对checkpoint之后的redo log进行恢复就可以了
  4. 如果redo log过多, 此时check point还没有推进, write pos就追上了check point, 那么就必须等待check point向前推进, 此时MySQL无法处理更新操作

回滚日志(undo log)

重做日志记录了事务的行为,可以很好的通过其对页进行“重做”操作。但是事务有时候还需要进行回滚操作,也就是ACID中的A(原子性),这时就需要Undo log了。因此在数据库进行修改时,InnoDB存储引擎不但会产生Redo,还会产生一定量的Undo。这样如果用户执行的事务或语句由于某种原因失败了,又或者用户一条ROLLBACK语句请求回滚,就可以利用这些Undo信息将数据库回滚到修改之前的样子。

Undo log是InnoDB MVCC事务特性的重要组成部分。当我们对记录做了变更操作时就会产生Undo记录,Undo记录默认被记录到系统表空间(ibdata)中,但从5.6开始,也可以使用独立的Undo 表空间。

Undo记录中存储的是老版本数据,当一个旧的事务需要读取数据时,为了能读取到老版本的数据,需要顺着undo链找到满足其可见性的记录。当版本链很长时,通常可以认为这是个比较耗时的操作。

undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。

undo log只将数据库逻辑地恢复到原来的样子,在回滚的时候,它实际上是做的相反的工作,比如一条INSERT ,对应一条 DELETE,对于每个UPDATE,对应一条相反的 UPDATE,将修改前的行放回去。undo日志用于事务的回滚操作进而保障了事务的原子性。

在InnoDB存储引擎中,undo存储在回滚段(Rollback Segment)中,每个回滚段记录了1024个undo log segment,而在每个undo log segment段中进行undo 页的申请,在5.6以前,Rollback Segment是在共享表空间里的,5.6.3之后,可通过 innodb_undo_tablespace设置undo存储的位置。

在InnoDB存储引擎中,undo log分为:insert undo log、update undo log

二进制日志(bin log)

MySQL的主库(Master)对数据库的任何变化(创建表,更新数据库,对行数据进行增删改),都以二进制文件的方式记录与主库的Binary Log(即binlog)日志文件中。

图来自1Dump Thread Enhancement On MySQL-5.7.2

  1. redolog 是 InnoDB 特有的日志,binlog 属于 Server 层日志
  2. 有两份日志的历史原因
    • 一开始并没有 InnoDB,采用的是MyISAM,但 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档
    • InnoDB 是以插件的形式引入 MySQL 的,为了实现 crash-safe,InnoDB 采用了 redolog 的方案
  3. binlog 一开始的设计就是不支持崩溃恢复(原库)的,如果不考虑搭建从库等操作,binlog 是可以关闭的(sql_log_bin)

redolog vs binlog

  • redolog 是 InnoDB 特有的,binlog 是 MySQL 的 Server 层实现的,所有层都可以使用

  • redolog 是物理日志,记录某个数据页上做了什么修改

    • binlog 是逻辑日志,记录某个语句的原始逻辑
    • 逻辑日志:提供给别的引擎用,是大家都能理解的逻辑,例如搭建从库
    • 物理日志:只能内部使用,其他引擎无法共享内部的物理格式
  • redolog 是循环写,空间固定,不能持久保存,没有归档功能

    • binlog 是追加写,空间不受限制,有归档功能
  • redolog 主要用于 crash-safe,原库恢复

    • binlog 主要用于恢复成临时库(从库)
  • 崩溃恢复的过程不写 binlog(可能需要读 binlog,如果 binlog 有打开,一般都会打开)

    • 用 binlog 恢复实例(从库),需要写 redolog
  • redolog 支持事务的持久性,undolog 支持事务的隔离性

  • redolog 对应用开发来说是透明的

binlog 有两种模式

statement 格式:SQL 语句

row 格式:行内容(记两条,更新前和更新后),推荐

  1. 日志一样的可以用于重放

基于 Binlog 的流式日志抽取的架构与原理

从库的 IO Thread 异步地同步 Binlog 文件并写入到本地的 Replay 文件。SQL Thread 再抽取 Replay 文件中的 SQL 语句在从库进行执行,实现数据更新。 需要注意的是,MySQL Binlog 支持多种数据更新格式 – 包括 Row,Statement,或者 mix(Row 和 Statement 的混合)。我们建议使用 Row 这种 Binlog 格式(MySQL5.7 之后的默认支持版本),可以更方便更加实时的反映行级别的数据变化。


图来自让你的数据库流动起来 – 利用MySQL Binlog实现流式实时分析架构

我们利用一些客户端工具 佯装 成 MySQL Slave,抽取出 Binlog 的日志文件,并把数据变化注入到实时的流式数据管道中。我们在管道后端对 Binlog 的变化日志,进行消费与必要的数据处理(例如利用AWS的Lambda服务实现无服务器的代码部署),同步到多种异构数据源中 – 例如 Redshift, ElasticSearch, S3 (EMR) 等等。具体的架构如下图所示。

中继日志(relay log)


图片来自MySQL 主从复制 完全上手指南


图片来自MySQL Replication

thanks

  1. MySQL学习笔记二
  2. MySQL 持久化保障机制-redo 日志
  3. 说说MySQL中的Redo log Undo log都在干啥
  4. MySQL InnoDB存储引擎事务的ACID特性
  5. MySQL -- redolog + binlog
  6. 图文并茂,带你了解SQL更新的过程

redo log 的参数 innodb_flush_method

mysql 的 innodb_flush_method 这个参数控制着 innodb 数据文件及 redo log 的打开、刷写模式,对于这个参数,文档上是这样描述的:

有三个值:fdatasync(默认),O_DSYNC,O_DIRECT

  • fdatasync,调用 fsync() 去刷数据文件与 redo log 的 buffer
  • 为 O_DSYNC 时,innodb 会使用 O_SYNC 方式打开和刷写 redo log,使用 fsync() 刷写数据文件
  • 为 O_DIRECT 时,innodb 使用 O_DIRECT 打开数据文件,使用 fsync() 刷写数据文件跟 redo log

首先文件的写操作包括三步:open,write,flush

  • 上面最常提到的 fsync(int fd) 函数,该函数作用是 flush 时将与 fd 文件描述符所指文件有关的 buffer 刷写到磁盘,并且 flush 完元数据信息(比如修改日期、创建日期等)才算 flush 成功。
  • 使用 O_DSYNC 方式打开 redo 文件表示当 write 日志时,数据都 write 到磁盘,并且元数据也需要更新,才返回成功。
  • O_DIRECT 则表示我们的 write 操作是从 MySQL innodb buffer 里直接向磁盘上写。

这三种模式写数据方式具体如下:

  • fdatasync 模式:写数据时,write 这一步并不需要真正写到磁盘才算完成(可能写入到操作系统 buffer 中就会返回完成),真正完成是 flush 操作,buffer 交给操作系统去 flush,并且文件的元数据信息也都需要更新到磁盘。
  • O_DSYNC 模式:写日志操作是在 write 这步完成,而数据文件的写入是在 flush 这步通过 fsync 完成
  • O_DIRECT 模式:数据文件的写入操作是直接从 mysql innodb buffer 到磁盘的,并不用通过操作系统的缓冲,而真正的完成也是在 flush 这步,日志还是要经过 OS 缓冲

原文链接:针对innodb_flush_method参数的理解和对比测试(mycat+mysql)

 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

戏剧牡丹亭

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文