快速带你读懂MySQL的Binlog写入机制

数据库 MySQL
如果 MySQL 服务器在崩溃恢复时发现二进制日志比应有的短,则它至少缺少一个成功提交的 InnoDB 事务。如果 sync_binlog=1 并且磁盘/文件系统在请求时进行实际同步(有些则没有),则不会发生这种情况,所以服务器打印一条错误消息日志。在这种情况下,此二进制日志不正确,应从源数据的新快照重新启动复制。

深入讲解MySQL中的重要日志 binlog 的写入机制以及影响IO性能的关键配置,并且介绍了如何利用binlog去恢复数据,保证MySQL的可靠性。

Q:binlog写入时机

binlog 的写入逻辑并不复杂:事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中。

什么是binlog cache?

binlog cache 在事务的运行期间暂存着binlog的数据,binlog cache 是在每个线程内空间独立的。如果启用了bin log日志,MySQL 会为每个客户端分配一个二进制日志缓存。如果您经常使用大型事务,则可以增加此缓存大小以获得更好的性能,可通过 binlog_cache_size 配置其大小,默认 32768 bytes。

如果binlog cache空间足够,在事务提交的时候,cache中的内容会被清空,同时这些数据会被写入到 binlog files 中;因为 bin log内容无论多大在事务提交时都需要一次性写入,所以当 bin log cache放不下的时候,就需要暂存到磁盘,然后提交被写入到 binlog files。

参数 binlog_cache_size:控制单个线程内 binlog cache 所占内存的大小

上面说的 写入到 bin log 中其实又拆为两部分:

  • write首先会写入 page cache 中的 binlog files 中,page cache 就是一块内存。(不占用磁盘IOPS)
  • fsync然后操作系统执行 fsync 时 bin log 才会从 page cache 中真正持久化到磁盘。(占用磁盘IOPS)

write 和 fsync写入时机

关于write和fsync 的时机,是通过参数 sync_binlog 控制:

  • sync_binlog=0:表示每次提交事务只是 write,不执行 fsync,也就是binlog不做持久化。(不建议)
  • sync_binlog=1:表示每次提交事务都要发生 fsync。
  • sync_binlog=N:表示每次事务都会write,但是N次事务提交会执行fsync进行持久化。

通常来说,为了提高IOPS,会将这个参数设为100-1000。缺点是如果还没有执行fsync就宕机,最多会丢失最近N个事务的binlog日志。如果为了保证数据安全,就设为1。

如果binlog内容缺失怎么办?

对于通过 redo log 可以恢复数据,我们都已经知道了,但是如果 binlog 内容缺失呢?

根据 sync_binlog 参数描述,如果设置为大于一,就代表N次事务才会将log持久化到磁盘中。而与此同时,redo log 的 innodb_flush_log_at_trx_commit 参数设置为1,表示每次事务提交都会执行 fsync。

这就产生了一种可能,如果发生mysql服务器了crash,此时redolog已经做持久化,但是binlog还有事务仍保存在page cache中,没有来得及执行fsync。宕机后重启服务,依赖redolog恢复数据,就会出现binlog 长度比真实数据所应该需要的长度短的情况。

面对数据完整但是binlog缺失,这种情况下会出现什么异样呢?

如果 MySQL 服务器在崩溃恢复时发现二进制日志比应有的短,则它至少缺少一个成功提交的 InnoDB 事务。如果 sync_binlog=1 并且磁盘/文件系统在请求时进行实际同步(有些则没有),则不会发生这种情况,所以服务器打印一条错误消息日志。在这种情况下,此二进制日志不正确,应从源数据的新快照重新启动复制。

按照官方描述,如果将 sync_binlog设为1不会出现这种情况,如果出现了binlog比预期少,则会在服务器打印一条binlog日志的异常log:The binary log xxx is shorter than its expected size.

所以这种情况需要去人为干预处理,从最新的快照数据源重新复制。

如何使用binlog恢复历史数据?

binlog 会记录所有的逻辑操作,并且是采用“追加写”的形式,不会像redolog一样去覆盖日志文件。binlog 里面的数据是可靠的,一定是事务提交后的数据,这就全靠 redolog 来保证。

众所周知,我们可以通过 binlog 恢复任意时间点的数据,如何做到呢?

其实这是有前提的,我们必须要有定期备份全量数据的机制,比如半个月、每周、或者每天。

假定场景:比如今天中午12点有一次误删表数据,需要找回数据,如何做?

  • 首先,找到最近的一次全量备份,比如昨天凌晨1点,那就从这个备份恢复到临时库;
  • 然后,从备份的时间昨天凌晨1点开始,将备份的 binlog 依次取出来重放,直到今天中午12点的数据。

这样临时库就到达了误删数据之前的状态,然后可以把表数据从临时库取出来,按需求恢复到线上正式数据库。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2018-12-05 09:20:02

MySQL数据库索引

2018-04-09 16:35:10

数据库MySQLInnoDB

2019-06-13 21:31:19

AI

2021-09-13 22:34:56

区块链新基建数字化转型

2017-11-09 12:41:42

2023-06-26 00:26:40

I/OJava字节流

2021-03-05 09:10:19

base64编码

2024-02-26 07:39:16

2021-02-23 08:18:04

Java 反射机制

2019-06-04 15:27:49

InnoDB存储引擎

2010-05-18 12:24:16

MySQL binlo

2015-10-30 10:22:01

物联网互联网

2019-07-08 13:40:22

人工智能深度学习神经网络

2022-09-23 13:24:21

MySQL数据库

2021-05-09 09:06:24

Python批处理命令

2020-04-01 11:11:35

Hadoop运行环境分布式

2021-07-12 08:06:32

Java

2020-03-03 08:29:07

时延敏感网络TSN网络

2020-06-05 14:15:29

可视化数据集分析

2020-04-01 16:30:32

TCP互联网Linux
点赞
收藏

51CTO技术栈公众号