MySQL/MariaDB的binlog二进制日志的三种模式以及正确删除方法

  • A+
所属分类:MySQL&MariaDB  数据库
摘要

MySQL 5.5 中对于二进制日志 (binlog) 有 3 种不同的格式可选:Mixed,Statement,Row,默认格式是 Statement,本文将说说三种模式的区别和binlog的正确删除方法。

有时候会发现binlog突然间变得的很大,导致磁盘分区都满了,这时候就需首先需要对binlog做清除,清除binlog时,如果有一个活性的从属服务器,该服务器当前正在读取您正在试图删除的日志之一,则本语句不会起作用,而是会失败,并伴随一个错误。不过,如果从属服务器是休止的,并且您碰巧清理了其想要读取的日志之一,则从属服务器启动后不能复制。当从属服务器正在复制时,本语句可以安全运行。您不需要停止它们,当然清除binlog只是临时的动作,我更应该需要查出是什么东西导致了binlog的猛然增长。这个可以看binlog日志的内容应该很容易发现的。

一、Row Level

日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改。
优点:在row level模式下,bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了。所以row level的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程,或function,以及 trigger的调用和触发无法被正确复制的问题。

对于一个写入操作,row格式binlog分为四部分,仿次为: BEGIN -> Table_map -> Write_rows/Delete_rows/Update_rows -> COMMIT

优点:任何情况都可以被复制,这对复制来说是最安全可靠的;

和其他大多数数据库系统的复制技能一样;

多数情况下,从服务器上的表如果有主键的话,复制就会快了很多;

复制以下几种语句时的行锁更少:

* INSERT … SELECT

* 包含 AUTO_INCREMENT 字段的 INSERT

* 没有附带条件或者并没有修改很多记录的 UPDATE 或 DELETE 语句 执行 INSERT,UPDATE,DELETE 语句时锁更少;

 从服务器上采用多线程来执行复制成为可能;

缺点:row level下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如有这样一条update语句:update product set owner_member_id = ‘b’ where owner_member_id = ‘a’,执行之后,日志中记录的不是这条update语句所对应额事件(MySQL以事件的形式来记录bin-log日志),而是这条语句所更新的每一条记录的变化情况,这样就记录成很多条记录被更新的很多个事件。自然,bin-log日志的量就会很大。尤其是当执行alter table之类的语句的时候,产生的日志量是惊人的。因为MySQL对于alter table之类的表结构变更语句的处理方式是整个表的每一条记录都需要变动,实际上就是重建了整个表。那么该表的每一条记录都会被记录到日志中。

二、Statement Level

每一条会修改数据的sql都会记录到 master的bin-log中。slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行。

优点:statement level下的优点首先就是解决了row level下的缺点,不需要记录每一行数据的变化,减少bin-log日志量,节约IO,提高性能。因为他只需要记录在Master上所执行的语句的细节,以及执行语句时候的上下文的信息。

缺点:由于他是记录的执行语句,所以,为了让这些语句在slave端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端杯执行的时候能够得到和在master端执行时候相同的结果。另外就是,由于MySQL现在发展比较快,很多的新功能不断的加入,使MySQL得复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug也就越容易出现。在statement level下,目前已经发现的就有不少情况会造成MySQL的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如:sleep()函数在有些版本中就不能真确复制,在存储过程中使用了last_insert_id()函数,可能会使slave和master上得到不一致的id等等。由于row level是基于每一行来记录的变化,所以不会出现类似的问题。

三、Mixed Level

实际上就是前两种模式的结合。在Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。新版本中的Statment level还是和以前一样,仅仅记录执行的语句。而新版本的MySQL中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录,如果sql语句确实就是update或者delete等修改数据的语句,那么还是会记录所有行的变更。

四、在配置文件中参数

log-bin=mysql-bin
#binlog_format=”STATEMENT”
#binlog_format=”ROW” binlog_format=”MIXED” 运行时在线修改:
mysql> SET SESSION binlog_format = ‘STATEMENT’;
mysql> SET SESSION binlog_format = ‘ROW’;
mysql> SET SESSION binlog_format = ‘MIXED’;
mysql> SET GLOBAL binlog_format = ‘STATEMENT’;
mysql> SET GLOBAL binlog_format = ‘ROW’;
mysql> SET GLOBAL binlog_format = ‘MIXED’;

五、删除&关闭binlog日志

1、关闭binlog

#修改配置文件,注释下面的几行就OK
[root@LookBack ~]# cat /etc/my.cnf | grep -E 'log[_-]bin|binlog_format|expire_logs_days' #这是查询语句
log_bin = mysql-bin #是否开启了二进制日志
binlog_format = mixed #二进制日志记录的模式
expire_logs_days = 30 #二进制日志自动删除的天数。默认值为0,表示"没有自动删除"

2、正确删除binlog

PURGE MASTER LOGS TO 'MySQL-bin.010'; #清除MySQL-bin.010日志
PURGE MASTER LOGS BEFORE '2015-07-19 13:50:42'; #清除2015-07-19 13:50:42前binlog日志
PURGE MASTER LOGS BEFORE DATE_SUB( NOW( ), INTERVAL 3 DAY); #清除3天前binlog日志BEFORE,变量的date自变量可以为'YYYY-MM-DD hh:mm:ss'格式
lookback

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:2   其中:访客  2   博主  0

    • avatar lalal 0

      我就是来看隐藏内容的

      • avatar ttw 0

        看看先~