写在前面的话

1、推荐用mixed,默认使用statement,基于上下文  set session/global binlog_format=mixed;

2、二进制日记录了数据库执行更改的操作,如Insert,Update,Delete等。不包括Select等不影响数据库记录的操作

3、MySQL记录的日志有三种模式:STATEMENT、ROW、MIXED

4、二进制主要的功能有:复制(Replication)和恢复(Recovery)

5、ROW与STATEMENT不同之处主要在于,服务器负载/一致性两个方面

复制的历史

mysql-3.2 开始支持基于命令的复制,也就是statement-based replication。
mysql-5.1 开始支持基于行的复制和混合复制,也就是row-based replication和mixed-based relication。
mysql-5.5 开始支持semi-synchronous的复制,也叫半同步复制,目的在于事务环境下保持主从一致。
mysql-5.6 开始支持并行复制,但是其并行只是基于schema的
mysql-5.7 开始支持基于组提交的并行复制

复制的基本过程如下:

(1)Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容
(2)Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置
(3)Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中
(4)Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行

redolog 和 undolog

undolog 实现原子性。每当操作数据前,首先将数据备份到一个地方(这个存储数据备份的地方称为undolog)。然后再修改数据。如果出现了错误或者用户执行了rollback语句,可以利用undolog中的备份将数据恢复到事务开始之前的状态。

redolog 实现持久性。每当操作数据前,将数据真正更改时,先前相关操作写入重做日志。这样当断电,或者一些意外,导致后续任务无法完成时,系统恢复后,可以继续完成这些更改执行这些操作来恢复数据。 比如某一时刻数据库down机了,有两个事务,一个事务已经提交,另一个事务正在处理数据库重启的时候就要根据日志进行前滚及回退,把已提交事务的更改写到数据文件,未提交事务的更改恢复到事务开始前的状态。

Row based replication-RBR

日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行回放,和其他大多数数据库系统的复制技能一样

优点:bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了。所以row level的日志内容会非常清楚的记录下每一行数据修改的细节

1、任何情况都可以被复制,这对复制来说是最安全可靠的,不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题
2、多数情况下,从服务器上的表如果有主键的话,复制就会快了很多,执行 INSERT,UPDATE,DELETE 语句时锁更少,复制以下几种语句时的行锁更少
  • INSERT ... SELECT
  • 包含 AUTO_INCREMENT 字段的 INSERT
  • 没有附带条件或者并没有修改很多记录的 UPDATE 或 DELETE 语句

缺点:所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容

比如有这样一条update语句:update product set owner_member_id = 100 where owner_member_id = 1 ,执行之后,日志中记录的不是这条update语句所对应额事件(MySQL以事件的形式来记录bin-log日志),而是这条语句所更新的每一条记录的变化情况,这样就记录成很多条记录被更新的很多个事件。

执行alter table之类的语句的时候,产生的日志量是惊人的。因为MySQL对于alter table之类的表结构变更语句的处理方式是整个表的每一条记录都需要变动,实际上就是重建了整个表。那么该表的每一条记录都会被记录到日志中

  • binlog 大了很多,复杂的回滚时 binlog 中会包含大量的数据
  • 执行 UPDATE 语句时,所有发生变化的记录都会写到 binlog 中,这会导致频繁发生 binlog 的并发写
  • UDF 产生的大 BLOB 值会导致复制变慢
注:采用 RBR 模式后,能处理很多原先出现的主键重复问题

Statement based replication-SBR

每一条会修改数据的sql都会记录到 master的bin-log中,而且记录每条语句在执行的时候的一些相关信息,也就是上下文信息

优点:不需要记录每一行数据的变化,减少bin-log日志量,节约IO,提高性能。主从版本可以不一样,从服务器版本可以比主服务器版本高

缺点:由于记录的执行语句,所以为了让这些语句在slave端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息

另外就是,很多的新功能不断的加入,使MySQL得复制遇到了不小的挑战。目前已经发现的就有不少情况会造成MySQL的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如:sleep() 函数在有些版本中就不能真确复制,在存储过程中使用了last_insert_id()函数,可能会使slave和master上得到不一致的id等等

1、不是所有的UPDATE语句都能被复制,尤其是包含不确定操作的时候

2、调用具有不确定因素的 UDF 时复制也可能出问题,确定了的 UDF 也须要在从服务器上执行

3、运用以下函数的语句也不能被复制:LOAD_FILE()、UUID()、USER()、FOUND_ROWS()、SYSDATE() (除非启动时启用了 --sysdate-is-now 选项)

4、INSERT ... SELECT 会产生比 RBR 更多的行级锁,复制须要执行全表扫描(WHERE 语句中没有运用到索引)的 UPDATE 时,须要比 RBR 请求更多的行级锁

6、对于有 AUTO_INCREMENT 字段的 InnoDB表而言,INSERT 语句会阻塞其他 INSERT 语句

7、对于一些复杂的语句,在从服务器上的耗资源情况会更严重,而 RBR 模式下,只会对那个发生变化的记录产生影响

8、存储函数(不是存储流程 )在被调用的同时也会执行一次 NOW() 函数,这个可以说是坏事也可能是好事

10、数据表必须几乎和主服务器保持一致才行,否则可能会导致复制出错

11、只支持REPEATABLE READ可重复读和以上的隔离级别

Mixed based replication-MBR

触发器(TRIGGER):
ROW
主上有,从上没有,复制正常,数据正常。
主上有,从上也有,复制正常,数据正常。 STATEMENT/MIXED
主上有,从上没有,复制正常,数据不正常,触发器里面的sql语句没有执行。
主上有,从上也有,复制正常,数据正常。 函数(FUNCTION):
ROW
主上有,从上没有,复制正常,数据正常。日志里记录的是UDF转换过的结果。
主上有,从上也有,复制正常,数据正常。 STATEMENT/MIXED
主上有,从上没有,复制报错。从不识别UDF函数。
主上有,从上也有,复制正常,数据正常。 存储过程(STORED PROCEDURES)
ROW
主上有,从上没有,复制正常,数据正常。记录的不是call sp,而是SP里面的sql。
主上有,从上也有,复制正常,数据正常。 STATEMENT/MIXED
主上有,从上没有,复制正常,数据正常。记录的不是call sp,而是SP里面的sql。
主上有,从上也有,复制正常,数据正常。 事件(event):
ROW
主上有,从上没有,复制正常,数据正常。记录的不是计划,而是EVENT里面的sql。
主上有,从上也有,复制正常,数据正常。(默认,DISABLE ON SLAVE),ALTER EVENT event_name ENABLE/DISABLE STATEMENT/MIXED
主上有,从上没有,复制正常,数据正常。记录的不是计划,而是EVENT里面的sql。
主上有,从上也有,复制正常,数据正常。(默认,DISABLE ON SLAVE), ALTER EVENT event_name ENABLE/DISABLE

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

以下几种情况下会自动将binlog的模式由 SBR 模式改成 RBR 模式

  • 当DML语句更新一个NDB表时
  • 当函数中包含 uuid(),user(),current_user(),found_rows(),row_count(),等不确定函数
  • 2个及以上包含 AUTO_INCREMENT 字段的表被更新时
  • 行任何 INSERT DELAYED 语句时
  • 使用了用户定于的函数(UDF) 时
  • 视图中必须要求运用 RBR 时,例如建立视图是运用了 UUID() 函数
  • 使用了临时表(temporary table)
 新的基于行模式,用法是 binlog-row-image=minimal 设置该选项后,对于DML操作修改的数据,只有发生变化的字段才保存到binlog里面,(insert和delete还是全字段)。这提高了master和slave的复制吞吐量,减小了binlog的磁盘占用,网络资源和内存使用。

另外,针对系统库 mysql 里面的表发生变化时的处理准则如下:

1、如果是采用 INSERT,UPDATE,DELETE 直接操作表的情况,则日志格式根据 binlog_format 的设定而记录
2、如果是采用 GRANT,REVOKE,SET PASSWORD 等管理语句来做的话,那么无论如何 都采用 SBR 模式记录
3、blockhole引擎不支持row格式,ndb引擎不支持statement格式
 

参考文章

https://dev.mysql.com/doc/refman/5.7/en/binary-log.html
https://dev.mysql.com/doc/refman/5.7/en/binary-log-formats.html
https://www.percona.com/blog/2013/01/09/how-does-mysql-replication-really-work/
https://www.percona.com/blog/2010/07/20/estimating-replication-capacity/
http://my.oschina.net/zijian1315/blog/202599
http://www.360doc.com/content/14/1107/14/12904276_423333021.shtml
https://www.percona.com/blog/2011/12/16/statement-based-replication-with-stored-functions-triggers-and-events/
http://www.tuicool.com/articles/vuUbyy
 

【mysql】关于binlog格式的更多相关文章

  1. MySQL 日志之 binlog 格式 → 关于 MySQL 默认隔离级别的探讨

    开心一刻 产品还没测试直接投入生产时,这尼玛... 背景问题 在讲 binlog 之前,我们先来回顾下主流关系型数据库的默认隔离级别,是默认隔离级别,不是事务有哪几种隔离级别,别会错题意了 1.Ora ...

  2. 20180530利用Maxwell组件实时监听Mysql的binlog日志

    转自:https://blog.csdn.net/qq_30921461/article/details/78320750 http://kafka.apache.org/quickstart htt ...

  3. mysql binlog格式

    Binlog Event 对于一个 Binlog Event 来说,它分为三个部分,header,post-header 以及 payload.MySQL 的 Binlog Event 有很多版本,我 ...

  4. mysql row日志格式下 查看binlog sql语句

    有时候我们需要使用row作为binlog的日志格式,即配置文件使用了binlog_format= row 参数 这样以来,我们在查看数据库binlog内容时候,就看不到增删改查的具体语句了,在数据库恢 ...

  5. MySQL binlog格式解析

    MySQL binlog格式解析   binlog想必大家都不陌生,在主从复制或者某些情况下的数据恢复会用到.由于binlog是二进制数据,要查看一般都借助mysqlbinlog工具.这篇笔记分析了b ...

  6. my15_ mysql binlog格式从mixed修改为row格式

    由于主库繁忙,就在从库上修改binlog格式 1. 从库切日志mysql> flush logs;Query OK, 0 rows affected (0.00 sec) mysql> f ...

  7. 浅析MySQL基于ROW格式的二进制日志

    上文分析的二进制日志实际上是基于STATEMENT格式的,下面我们来看看基于ROW格式的二进制日志,毕竟,两者对应的binlog事件类型也不一样,同时,很多童鞋反映基于ROW格式的二进制日志无法查到原 ...

  8. mysql开启binlog

    mysql开启binlog,至于为什么要开启binlog,可以google下. ## 设置server_id,一般设置为IP server_id= ## 复制过滤:需要备份的数据库名,多个库以逗号分隔 ...

  9. MySQL的binlog数据如何查看

    binlog介绍 binlog,即二进制日志,它记录了数据库上的所有改变. 改变数据库的SQL语句执行结束时,将在binlog的末尾写入一条记录,同时通知语句解析器,语句执行完毕. binlog格式 ...

  10. 解说mysql之binlog日志以及利用binlog日志恢复数据

    众所周知,binlog日志对于mysql数据库来说是十分重要的.在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定时全备份+binlog日志恢复增量数据部分),化险为夷! 废 ...

随机推荐

  1. Entity Framework 6 Recipes 2nd Edition(13-1)译 -> 优化TPT继承模型的查询

    问题 你想提高在一个TPT继承模型里的查询 解决方案 让我们假设有一个简单的TPT继承模型,如图Figure 13-1 Figure 13-1. A simple Table per Type inh ...

  2. 2016年8月ios面试问题总结

    1.app分发方式 所谓分发方式简单点讲就是你的app都可以通过哪些途径给用户使用. a:个人或者公司的开发者账号 可以上传appStore,用户通过appStore下载. b:企业账号:打包分发. ...

  3. Android 浏览器 —— 使用 WebView 实现文件下载

    对当前的WebView设置下载监听 mCurrentWebView.setDownloadListener(new DownloadListener() { @Override public void ...

  4. .NET Core采用的全新配置系统[7]: 将配置保存在数据库中

    我们在<聊聊默认支持的各种配置源>和<深入了解三种针对文件(JSON.XML与INI)的配置源>对配置模型中默认提供的各种ConfigurationSource进行了深入详尽的 ...

  5. ASP.NET 访问共享文件夹

    配置代码: var dataProtection = new Microsoft.AspNet.DataProtection.DataProtectionProvider(new DirectoryI ...

  6. console.log("A"-"B"+"3")=?

    (点击上方的订阅号,可快速关注,关注有惊喜哦^_^) 前不久看到一道JS基础题目,做了一下竟然错了一半...在此分享一下: 先把题目放上来,大家可以自己测试一下再看答案哦^_^ ①console.lo ...

  7. SQL Tuning 基础概述03 - 使用sql_trace和10046事件跟踪执行计划

    1.使用sql_trace跟踪执行计划 1.1 当前session跟踪: alter session set sql_trace = true; //开始sql_trace alter session ...

  8. Java进击C#——应用开发之Asp.net

    本章简言 上一章中笔者讲到关于Linq和EF的用法.并以hibernate来进行讲解.那么本章笔者来讲一下C#的Asp.Net.即是在B/S模式下开发.现在企业大部分的业务都是面向B/S模式的.所以对 ...

  9. MacOS平台下@rpath在动态链接库中的应用

    一.背景介绍 公司开发的一个底层库被用在了Mac平台的多个产品中.在开发这个底层库的初期,对于Mac OSX下的Install name 并没有过多的了解.对于XCode中的install name项 ...

  10. MFC AfxMessageBox默认标题修改

    在工程的资源String Table里面添加AFX_IDS_APP_TITLE,然后设置其值即可,AFX_IDS_APP_TITLE的值就是AfxMessageBox的标题