资讯详情

MYSQL中redo log和binlog之间的区别

参考 编程客栈

mysql它为我们提供了许多有用的日志mysql为我们提供的服务层:

日志类型 写日志信息
二进制日志 记录了对MySQL数据库执行更改的所有操作
慢查询日志 超过所有执行时间的记录 long_query_time 所有查询秒或无索引查询
错误日志 启动时记录,运行或停止mysqld问题
一般查询日志 记录客户端连接和执行的句子
中继日志 更改复制主服务器接收的数据

假设读者已经在这里了mysql对底层有一定的了解,知道一个sql句子的一般执行过程可能会更好地阅读本文

:InnoDB 存储引擎层的日志,所以如果你使用的存储引擎不是 InnoDB 如果根本谈不上, redo log。 : MySQL Server 层记录的日志,所以无论使用什么存储引擎,只要是 MySQL 都是会有 binlog 在做 MySQL 主从复制时使用 binlog。

接下来,让我们详细看看他们分别做了什么。

在这里插入图片描述

为什么要有这个? redo log 日志文件呢?

在这里,我们可以举个例子,现在我们想修改数据库的数据,现在一个 update 句子过来,一般 update 操作的操作都伴随着查询的操作,在更新操作之前,必须先找到数据。

如果数据量相对较小,可以很快找到并更新,但如果数据量相对较大,有1亿个数据,该怎么办?更新操作必须写在磁盘上,然后在中间 IO 成本呢?

假如我有几十个 update 句子已经更新了?如果你这样想,你会认为这些操作的成本很高。你能降低这些成本吗?

这时候,redo log 起作用。 当有记录更新时, InnoDB 引擎会先把记录写下来 redo log 内存同时更新,即使数据更新成功。

但此时它还没有更新到磁盘上,对吧?别担心, InnoDB 会在恰当的时候,把这条及记录更新到磁盘上去,而且这个更新往往是在系统比较空闲的时候进行的。

这种思想或技术有一个专有名词: WAL 技术,也就是WriteAheadLogging,核心就是先写日志,再写磁盘

redo log 不能一直写吧?

redo log 大小是固定的,前面的内容会被覆盖,一旦写满,就会触发 redo log 同步磁盘,以便腾出空间记录以后的修改。

数据库停机或重启,数据不会丢失。

因为有了 redo log ,以前提交的记录仍然存在,只需根据 redo log 内部记录可以相应恢复。

binlog 是 MySQL Server 层记录日志。 二进制日志(binnary log)以事件形式记录对MySQL所有更改数据库的操作。

binlog记录所有数据库表结构的变化CREATE、ALTER TABLE…)修改表数据(INSERT、UPDATE、DELETE…)的二进制日志。不会记录SELECT和SHOW这种操作,因为数据本身没有修改,但可以通过查询通用日志来查看MySQL所有已执行的句子。

mysql server层维护与使用什么引擎无关,记录所有更新操作的日志记录。binlog在事务的最后commit前面写的。我们执行SELECT不涉及数据更新的句子不会被记住binlog是的,数据更新将被记录下来。需要注意的是,支持事务的引擎,如innodb在记录之前,必须提交事务binlog

binlog 文件完成后,将自动切换到下一个日志文件继续写作,而不覆盖以前的日志,这也不同于 redo log,redo log 循环写入,即后面写入的可能覆盖前面写入。

binlog常用场景有两种:

  • 主从复制:我们将有一个专门的章节来代表每个人建造两个主从同步mysql服务。
  • 数据恢复:通过mysqlbinlog恢复数据的工具。

mysql8中的binLog默认情况放的,5.7默认是关闭的,可以通过参数log_bin控制:

(1)确认binlog开启,log_bin变量的值为ON代表binlog是开启状态:

show variables like '%log_bin%'; 

(2)为了防止干扰,我们flush刷新log从现在起,日志将产生一个新的编号binlog日志文件:

flush logs; 

(3)检查一切binlog日志列表:

show master logs; 

(4)查看master状态,即最后(最新)一个binlog日志的编号名称及其最后一次操作事件pos结束点,这一步可有可无:

(5)执行sql

先创建表格,插入一些数据:

DROP TABLE IF EXISTS ydl_student; CREATE TABLE `ydl_student` (   `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `score` int(255) DEFAULT NULL, `grade` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `ydl_student`(`id`, `name`, `score`, `grade`) VALUES (1, 'lucy', 80, 'a'); INSERT INTO `ydl_student`(`id`, `name`, `score`, `grade`) VALUES (2, 'lily', 90, 'a'); INSERT INTO `ydl_student`(`id`, `name`, `score`, `grade`) VALUES (3, 'jack', 60, 'c'); INSERT INTO `ydl_student`(`id`, `name`, `score`, `grade`) VALUES (4, 'hellen', 40, 'd'); INSERT INTO `ydl_student`(`id`, `name`, `score`, `grade`) VALUES (5, 'tom', 60, 'c'); INSERT INTO `ydl_student`(`id`, `name`, `score`, `grade`) VALUES (6, 'jerry', 10, 'd'); INSERT INTO `ydl_student`(`id`, `name`, `score`, `grade`) VALUES (7, 'sily', 20, 'd'); 

执行删除操作,假装误删除,直接全部删除也可以,把表删了都行,一样的道理:

delete from ydl_student where id in (3,5);

(6)查看binlog日志,我们因为刷新了日志,所以本次操作都会在最新的日志文件上:

因为 binlog 的日志文件是二进制文件,不能用文本编辑器直接打开,需要用特定的工具来打开,MySQL 提供了 mysqlbinlog 来帮助我们查看日志文件内容:

# 查看全部的日志信息
/www/server/mysql/bin/mysqlbinlog -v mysql-bin.000008
# 指定位置范围
/usr/bin/mysqlbinlog -v mysql-bin.000013 --start-position=0 --stop-position=986
# 指定时间范围
/usr/bin/mysqlbinlog -v mysql-bin.000013 --start-datetime="2022-06-01 11:18:00" --stop-datetime="2022-06-01 12:18:00" 

真实的情况下,我们的日志文件比较复杂,内容比较多使用时间范围查询后任然可能需要花费时间去排查问题,这里我们找到了误删除的位置:

(7)执行恢复,通过上一步的操作,我们找到了删除的位置3228(即第二个红框),执行下面的语句:

/www/server/mysql/bin/mysqlbinlog -v mysql-bin.000008 --stop-position=3228 -v | mysql -uroot -p

(8)至此,数据已完全恢复了:

binlog的数据恢复的本质,就是将之前执行过的sql,从开始到指定位置全部执行一遍,如果报错【当前表已经存在】,就将数据库的表删除,重新恢复。

redo log 和 binlog 的区别:

  • redo log 是 InnoDB 引擎特有的; binlog 是 MySQL 的 Server 层实现的,所有的引擎都是可以的。
  • redo log 是物理日志,记录的是”在 XXX 页上做了 XXX 修改”;binlog 是逻辑日志,比如” 给 id = 2 这一行的 c 字段加 1”。
  • redo log 是有固定大小的,所以它的空间会用完,如果用完的话,一定要进行一些写入磁盘的操作才可以继续;binlog 是可以追加写入的,也就是 binlog 没有空间的概念,一直写就行了。

binlog 以事件的形式记录了所有的 DDL 和 DML 语句(因为它记录的是操作而不是数据值,属于逻辑日志),可以用来做

在开启了 binlog 功能的情况下,我们可以把 binlog 导出成 SQL 语句,把所有的操作重放一遍,来实现数据的恢复。

有了这两个日志之后,我们来看一下一条更新语句是怎么执行的(redo 不能一次写入了):

例如一条语句:update user set name='小马' where id=1;

  • 先查询到这条数据,如果有缓存,也会用到缓存
  • 把 name 改成小马,然后调用引擎的 API 接口,写入这一行数据到内存,同时记录 redo log。这时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,可以随时提交。
  • 执行器收到通知后记录 binlog,然后调用存储引擎接口,设置 redo log为 commit 状态
  • 更新完成。

redo log 和 binlog 都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。

可以假设一下,如果不采用这种方式,而是就先写 redo log ,再写 binlog ,会怎样? 如果在写 binlog 时,发生了异常,更新操作已经到 redo log 中了,但是此时 binlog 并没有进行更新,是不是出现了数据不一致?

先写 binlog 再写 redo log 也是一样的道理。所以,在写时,先让 redo log 处于 prepare 状态,等 binlog 写完之后,再让 redo log 处于 commit 状态,这样就保持了逻辑上的一致。

-数据库连接池与connection分析

标签: ydl连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台