MySQL的binlog

MySQL的binlog

MySQL中的日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中比较重要的还要属 二进制日志 binlog(归档日志)和事务日志 redo log(重做日志)和 undo log(回滚日志)。

在“MySQL事务”一文中,介绍了重做日志和回滚日志的相关知识,包括如何通过redo log实现事务的持久性,通过undo log实现事务的原子性。本文主要介绍binlog相关知识。

1 概述

binlog 是逻辑日志,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于MySQL Server 层。 因此不管用什么存储引擎, 只要发生了表数据更新,都会产生 binlog 日志。 那 binlog 到底是用来干嘛的?

  1. 恢复

    某些数据的恢复需要二进制文件,例如,在一个数据库全备文件恢复后,用户可以通过二进制日志进行point-in-time恢复。

  2. 复制

    数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性。

  3. 审计

    用户可以通过查看二进制日志信息,判断是否有对数据库进行注入攻击。

在InnoDB中,binlog默认是没有启动的,需要手动指定参数log-bin来启动。启动该选项会对数据库整体性能有所影响,但是带来的损失十分有限。

2 记录格式

binlog有3中记录格式,从MySQL5.1开始可以通过binlog_format参数来指定:

  • statement:和早期版本一样,记录的是日志的逻辑。

    这种格式可能存在一些问题,比如undate_time=now(),这里会获取当前系统时间,导致主从库之间不一致。

  • row:记录表的行更改情况,更改前后的数据都记录下来了。

    这样就能保证同步数据的一致性,通常情况下都是指定为row,这样可以为数据库的恢复与同步带来更好的可靠性。 但是使用ROW格式可能占用更大的磁盘空间,而由于复制是采用传输二进制日志方式实现的,因此复制的网络开销也有所增加。

  • mixed:这种设定下MySQL默认采用statement格式记录binlog,但是在一些情况下会使用ROW格式,这些情况有:

    • 表的存储引擎为NDB,这时对表的DML操作都会以ROW格式记录;
    • 使用了UUID()、USER()、CURRENT_USER()等不确定函数;
    • 使用了insert delay语句;
    • 使用了用户定义函数;
    • 使用了临时表。

3 写入机制

binlog的写入时机也非常简单,事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。

因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache

我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap),因此cache的大小不能太大也不能太小。

binlog日志刷盘流程如下 :

  • 上图的 write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快
  • 上图的 fsync,才是将数据持久化到磁盘的操作

writefsync的时机,可以由参数sync_binlog控制,默认是0。为0的时候,表示每次提交事务都只write,由系统自行判断什么时候执行fsync

虽然性能得到提升,但是机器宕机,page cache里面的 binlog 会丢失。

为了安全起见,可以设置为1,表示每次提交事务都会执行fsync,就如同 redo log 日志刷盘流程 一样。

最后还有一种折中方式,可以设置为N(N>1),表示每次提交事务都write,但累积N个事务后才fsync

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2022 Yin Peng
  • 引擎: Hexo   |  主题:修改自 Ayer
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信