MySQL binlog模式导致的磁盘爆满

22 阅读3分钟

最近遇到一个服务器磁盘爆满的情况,其原因是过多的 MySQL 开启 binlog 的 ROW 模式后导致binlog 日志过多,占到200G左右。所以关闭了 MySQL 的 binlog 模式。打算了解一下binlog的作用。

1、binlog 的设计目标

binlog 记录了对 MySQL数据库执行更改的所有的写操作,包括所有对数据库的数据、表结构、索引等等变更的操作。

2、binlog 的应用场景

1、主从复制

在 Master 端开启 binlog ,然后将 binlog 发送到各个 Slave 端, Slave 端重放 binlog 来达到主从数据一致。

2、数据恢复

通过使用 mysqlbinlog 工具来恢复数据。

3、binlog 数据格式

1、ROW

基于行的复制(row-based replication, RBR),相当于修改记录,每一行数据的修改都会产生一个数据 。尤其在修改表结构的时候,由于记录的数量相当于表的行数,日志会激增。

优点:准确,不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题;

缺点:日志量太大

2、STATMENT

基于SQL语句的复制( statement-based replication, SBR ),每一条会修改数据的SQL语句会记录到 binlog 中 。即记录update语句,省空间

优点:不需要记录每一行的变化,减少了 binlog 日志量,节约了 IO , 从而提高了性能;

缺点:在某些情况下会导致主从数据不一致,比如执行sysdate() 、 slepp() 等 。

3、MIXED

基于 STATMENT 和 ROW 两种模式的混合复制(mixed-based replication, MBR),一般的复制使用 STATEMENT 模式保存 binlog ,对于一些函数,STATEMENT 模式无法复制的操作使用 ROW 模式保存 binlog。

4、特别注意

ROW格式更加适合用于数据同步与数据恢复上面,易于避免数据不一致的问题;相反,MIXED与STATMENT是基于SQL语句的,不同数据状态下会呈现不一样的效果,最终可能会导致数据不一致的效果。

4、写入策略

对于 InnoDB 存储引擎而言,在进行事务的过程中,首先会把binlog 写入到binlog cache中(因为写入到cache中会比较快,一个事务通常会有多个操作,避免每个操作都直接写磁盘导致性能降低),只有在事务提交时才会记录 binlog ,此时记录还在内存中,那么 binlog 是什么时候刷到磁盘中的呢?

MySQL 其实是通过 sync_binlog 参数控制 binlog 的刷盘时机,取值范围是 0-N:

  • 0:每次提交事务binlog不会马上写入到磁盘,而是先写到page cache。不去强制要求,由系统自行判断何时写入磁盘,在Mysql 崩溃的时候会有丢失日志的风险;
  • 1:每次提交事务都会执行 fsync 将 binlog 写入到磁盘;
  • N:每次提交事务都先写到page cach,只有等到积累了N个事务之后才 fsync 将 binlog 写入到磁盘,在 MySQL 崩溃的时候会有丢失N个事务日志的风险。

所以1为高一致性而0、N 均有日志丢失的风险。

5、情况分析

本次直接开启了ROW格式,而sync_binlog并没有设置。几天内就会记录大量日志于data目录下。而该环境只是非重要的开发环境,且没有主从同步的场景,不需要那么高的可用性,为减少维护成本直接注释 binlog 配置。

参考:硬核干货!一文掌握 binlog 、redo log、undo log-腾讯云开发者社区-腾讯云