MySQL复制日志格式

虽然使用MySQL很多年,但是有些细节在MySQL 5.1之后更新的就比较少了.乘着读<数据密集型应用系统设计>的时候再重新了解一下.

当然关系型数据库系统是非常复杂的系统,先了解下复制的日志格式.

我们都知道MySQL的replication的日志一般都会选用mixed格式,但是默认其实是基于行的( row-based replication RBR). 早期还有基于语句的(statement-based replication SBR)

从理想层面来看,基于语句的更方便,而且同步的数据量会更小,只要记录变更的语句,同步过去后再slave上重新执行就行了.那为什么还有基于行的呢.

在<数据密集型应用系统设计>一书中的第152页中说明主要有如下3中情况不适用基于语句的.

  1. 任何调用非确定性函数的语句,比如now()获取当前时间,或者RAND()获取随机数. 在MySQL的官方文档里也列出了这些函数.
  2. 如果语句中使用了自增列,或者依赖于数据库的现有数据,则所有副本必须按照完全相同的顺序执行,否则会带来不同的结果. 这个也比较好理解,比如update 一个值,先乘以10再加5 和 先加5再乘以10那得到的结果肯定是不一样的.但是如果基于语句的复制,那就必须按顺序执行才行,不然肯定会出错.
  3. 有副作用的语句(例如触发器,存储过程,用户自定义的函数)

不过实际情况还有如下一些情况是使用基于行的.

  1. 涉及 mysql系统库的日志表:当语句操作的对象是mysql 数据库中的日志表时
  2. 不安全的语句,例如不带order by的limit更新等等

但是在互联网公司的实际项目中,以上问题都是需要通过制度来规避掉的. 比如uuid和rand的生成我直接在程序代码中生成,然后在insert进去, 如果使用自增id,那还必须有一列来表示也表示业务的id. limit 语句都必须要显式的指定limit等等.

当然现在MySQL越来越成熟了,有些问题系统也都会以warning日志来提醒你了.