MySQL – 日志

WAL机制

Write-Ahead Logging,预写日志系统即当有数据更新请求的时候,先写日志,再改内存,等”有空”的时候再落磁盘(刷脏页)。WAL机制的好处,因为写日志是磁盘顺序IO,而直接写磁盘是随机IO,性能较差。

binlog

MySQL server层自己的归档日志叫做binlog (binary log)。binlog会记录所有逻辑操作,采用”追加写”的方式,log不会被覆盖。

binlog的三种格式

binlog有三种格式(binlog_format),一种叫statement, 一种叫row, 第三种叫mixed, 是前两种的混合。举个栗子🌰:

delete from t where code

如果binlog是statement的形式,binlog将记录SQL原文:

MySQL - 日志

(ps 但是这条语句会产生一个warning,因为binlog设置为statement格式,语句有limit可能是unsafe的, 至于原因这里暂时不讨论,可以看链接)

如果binlog是row的形式,binlog不是记录SQL的原文而是替换成了两个event,table_map和delete_rows:

MySQL - 日志

binlog的使用场景

  • 主从复制
  • 数据恢复

如何将数据库恢复到之前的某个时刻?

找到这个时刻之前最近的一次全量备份,再从备份的时间点开始把binlog依次取出来,重放到需要恢复的那个时刻。

binlog的落盘时机

根据参数 sync_binlog来控制:

参数值 含义 0 不控制binlog刷新,由文件系统控制它缓存落盘,风险较大,一旦crash, 会有binlog丢失的问题 1 每次事务提交都会刷盘到磁盘,最安全但是性能最差。 N 每N次事务提交才会刷盘到磁盘

redo log

上面说binlog记录的是所有逻辑操作,且是server层面实现的,而redo log 记录的是数据页中的真实二进制数据,是在InnoDB存储引擎层面实现的。

redo log 包含两部分,一个是日志缓冲区(redo log buffer),一个是磁盘上的日志文件(redo log file)。InnoDB的redo log是固定大小,配置为一组4个文件,每个文件1GB,机制是循环写。 write pos记录当前从哪里开始写,写之后就向后移动, check point记录可以写到哪个位置。从 write poscheck point的区间(绿色部分)就是可以写日志的区域,如下图:

MySQL - 日志

既然叫 check point,那何时去check呢?(=什么时候刷脏页/flush?=什么时候算WAL中提到的”有空”)

脏页的落盘时机

  • 第一直觉上来说,如果redo log写满了,也就是说write pos追上check point了,那必须要刷脏页,把check point往后推,否则系统就无法处理更新了。
  • 第二个就是写内存的时候,发现内存不够用了,需要释放掉一些内存。在存储部分提到过,内存里的要么是空页,要么是干净页,要么是脏页。如果是干净页,就可以直接释放,如果是脏页就必须要先落盘flush
  • “有空”自然是说系统较为空闲的时候,因为WAL机制本身就是为了提高系统的性能,减少随机IO带来的性能损耗。如果系统负载很小,完全handle得过来,那就刷下脏页吧
  • MySQL需要关闭以前。那自然是要把数据落到磁盘上。

刷脏页的能力

可以通过 innodb_io_capacity参数告诉InnoDB这个磁盘的能力,一般是设置为磁盘的IOPS(Input/Output Per Second)。InnoDB会根据这个参数和当前内存的脏页比例以及redo log的落盘四度决定刷脏页的速度。

除此之外,刷脏页还有个特点就是”连坐”。如果当前需要被刷的这个脏页的邻居页也是脏页,那也会被一起刷到磁盘。可以通过设置 innodb_flush_neighbors参数为0来避免。

redo log的落盘时机

前面说的刷脏页,其实是把内存的最新数据更新到磁盘上,而上面也说了redo log其实也有缓存和磁盘文件,那redo log什么时候把缓存给落盘呢?

首先,我们要知道计算机操作系统的用户空间的缓冲区数据,要经过内核空间,由系统调用 fsync()写到磁盘上,如下图:

MySQL - 日志

可以通过 innodb_flush_log_at_trx_commit参数来配置这个redo log的落盘时机:

参数值 含义 0(延迟写) 事务提交时,不会将 redo log buffer中的日志写入os buffer; 而是每秒写入os buffer并调用 fsync()

写入redo log file中。也就是说当系统崩溃,会丢失1s的数据 1(实时写,实时刷) 事务提交时,都会将redo log buffer中的日志写入os buffer并调用 fsync()

刷到redo log file中。这种方式不会丢失任何数据,但是IO性能相对来说比较差 2(实时写,延迟刷) 事务提交时,都会写入os buffer,但是每秒调用 fsync()

将os buffer中的日志写入redo log file

redo log的使用场景

InnoDB通过redo log来实现事务,同时保证数据库即使发生异常重启,之前提交的记录都不会丢失,没有提交的事务数据自动回滚。这个能力就叫做crash-safe。

redo log & binlog

比较项 redo log binlog 记录的内容 物理日志,记录的是对XX表空间的XX数据页XX偏移量的地方做了XX更新, 恢复速度快 逻辑日志,如真实的SQL语句,如对XX表条件为XX的数据做了什么修改,需要逐条执行,恢复速度慢 记录的方式 循环写 追加写 用途 重做数据页 主从复制,数据备份 层级 innodb存储引擎提供 mysql server层提供

为什么要两个日志,一个不行吗?

redo log是InnoDB提供的,MySQL很早之前还没有InnoDB这个东西,都是用binlog来归档的。但是单独的binlog不能提供crash-safe的能力。

两阶段提交

一条更新语句,到底是怎样执行的呢?例如 update t set number=number+1 where id=1

MySQL - 日志

两阶段提交即将写入redo log这个操作,拆成了写prepare和写commit。由此可以保证redo log和binlog的逻辑一致性,避免主从复制时产生数据不一致的问题。

试想先写redo log再写binlog或者先写binlog再写redo log会有什么问题:

  • 先写redo log, 此时MySQL(master)崩溃(没来得及刷脏页),那么binlog里面这条数据还是原来的。MySQL(master)重启,会根据redo log来重放,那么此时master的数据是更新过后的,而从节点通过binlog去做复制的时候,这条数据就是老的。主比从多了一次数据更新。
  • 先写bin log, 此时MySQL(master)崩溃,那么redo log里面这条数据是旧的。MySQL(master)重启,根据redo log来重放,那么此时master的数据是原来的,而从节点通过binlog去做复制的时候,这条数据就是新的。从比主多了一次数据更新。

不过,两阶段提交不会有问题:

[En]

However, there will be no problem with two-phase submission:

  • 如果写入了redo log – prepare, MySQL崩溃,此时binlog啥也没有。MySQL重启,根据redo log重放的时候发现redo log是prepare但是binlog啥也没有,那就回滚。从节点根据binlog复制,不会有这条记录;master回滚了,也不会有这条记录。
  • 如果写入了redo log -prepare, 写入了binlog, MySQL崩溃,此时binlog是有数据的。MySQL重启,根据redo log重放的时候发现redo log是prepare但是binlog有对应的记录,那就提交。从节点根据binlog复制,会有这条记录;master提交了,也会有这条记录
  • 如果写入了redo log-prepare,写入了binlog, 写入了redo log-commit过后,MySQL崩溃了。MySQL重启,就按部就班重放redo log就行了,啥也不用做。

Original: https://www.cnblogs.com/rachel-aoao/p/mysql_log.html
Author: rachel_aoao
Title: MySQL – 日志

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/507824/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • SQLyog企业版

    一、下载与安装 1、SQLyog的下载 链接:https://www.aliyundrive.com/s/11ZuFqB1z4E提取码:63fu 2、SQLyog的安装 双击下载程…

    数据库 2023年6月11日
    0107
  • 配置nginx只打印延迟超过0.1s和非2XX的accesslog

    背景 当业务accesslog全开时,写入es的qps达到了10W,评估后觉得不太值得,所以考虑抽样打印。查看相关文档后发现目前我们使用的nginx版本不支持抽样打印,所以考虑其他…

    数据库 2023年6月9日
    073
  • 新的开始

    今天,我正式开始我的博客分享,java人加油 posted @2022-03-05 21:25 小小羊儿 阅读(10 ) 评论() 编辑 Original: https://www…

    数据库 2023年6月11日
    083
  • Qt 的事件监听和事件过滤

    Qt 产品级的开发项目中经常会用到一些自定义控件,从而达到一些可定制化的效果,这时候往往需要重写它的监听事件,满足产品的需求。这里用一个简单的例子记录一下思路: 新建一个DiyLa…

    数据库 2023年6月16日
    084
  • Elasticsearch搜索引擎的使用

    当用户在搜索框输入关键字后,我们要为用户提供相关的搜索结果。 这种需求依赖数据库的模糊查询like关键字可以实现,但是like关键字的效率极低,而且查询需要在多个字段中进行,使用l…

    数据库 2023年6月14日
    0126
  • Vue(十三)—过滤器filter,filters

    官网:https://cn.vuejs.org/v2/api/#filters https://cn.vuejs.org/v2/api/#Vue-filter 分为全局过滤器和局部…

    数据库 2023年6月16日
    083
  • 5、枚举Enum

    枚举类会 隐式的继承Enum类,无法再继承其它类( 单继承机制) 一、无实参枚举类型: 1、定义: /** * 1、无实参枚举类型 */ public enum NoParamTy…

    数据库 2023年6月6日
    091
  • select,poll,epoll

    select、poll、epoll 区别总结: 底层实现 select/poll 首先把关注的Socket集合从用户态拷贝到内核态,然后由内核检测事件,遍历整个集合(由于线性结构实…

    数据库 2023年6月16日
    087
  • windows安装mysql8.0.29(ZIP解压安装版本)

    一. 下载mysql 8.0.29软件包 二. 解压,初始化安装 1,打开下载后文件所在目录,使用解压软件解压,打开文件夹!(如图,文件路径不要出现中文!) 2,创建my.ini文…

    数据库 2023年6月16日
    073
  • mysql多表关联时可能出错的地方,如搜索出的记录数据变少了。

    当多个表相关联时,就会出现此问题。 [En] This problem occurs when multiple tables are associated.例如其中单位串以单位表…

    数据库 2023年5月24日
    071
  • 学习笔记——Django项目中的请求与响应

    2022-10-01 ALLOWED_HOSTS “ALLOWED_HOSTS”的含义: 它是指允许放在”ALLOWED_HOSTS&#8221…

    数据库 2023年6月14日
    080
  • 智慧 ~ 引子 ~ 三则故事

    年轻人的故事 从前,有位乡下青年,读了点书,嫌乡村的生活单调,决定要去城里闯世界。临走时,他向村中的村长请教,村长给了他三个字的忠告:”不要怕”。并讲好等他…

    数据库 2023年6月9日
    069
  • MyBatis(二)-CURD (ResultMap 一对一,一对多)

    1、insert 标签 1.1 获取SqlSessionFactory 对象的通用方法 方便后面分测试; //获取SqlSessionFactory 对象的通用方法 public …

    数据库 2023年6月16日
    067
  • Java面向对象(上)

    Java面向对象(上) 一、面向对象的思想 1、面向过程: 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤逐一实现,使用的时候依次调用就可以了。 2、面向对象: 面向…

    数据库 2023年6月11日
    090
  • js中创建正则对象时,变量中存在转义字符(’/’,’.’等)时,是否需要转义?

    使用直接量创建正则时,很方便,但是如果存在变量时,不适用。 使用正则对象(RegExp)创建时,对于变量中的转义字符不需要处理。 另外测试正则地址: https://develop…

    数据库 2023年6月11日
    098
  • 【Java基础】– FileUtils工具类常用方法

    1.FileUtils介绍 文件IO是我们日常项目中经常使用到的基础API,常见的IO读写操作基础类字节流InputStream与OutputStream、字符流Reader与Wr…

    数据库 2023年6月6日
    0345
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球