1、基于语句的复制(statement-Based Replication)
MySQL5.0及之前的版本仅支持基于语句的复制(也叫做逻辑复制,logical replication)。master记录下改变数据的查询,然后,slave从中继日志中读取事件,并执行它,这些SQL语句与master执行的语句一样。这种方式的优点就是实现简单。此外,基于语句的复制的二进制日志可以很好的进行压缩,而且日志的数据量也较小,占用带宽少——例如,一个更新GB的数据的查询仅需要几十个字节的二进制日志。而mysqlbinlog对于基于语句的日志处理十分方便。
但是,基于语句的复制并不是像它看起来那么简单,因为一些查询语句依赖于master的特定条件,例如,master与slave可能有不同的时间。所以,MySQL的二进制日志的格式不仅仅是查询语句,还包括一些元数据信息,例如,当前的时间戳。即使如此,还是有一些语句,比如,CURRENT USER函数,不能正确的进行复制。此外,存储过程和触发器也是一个问题。
另外一个问题就是基于语句的复制必须是串行化的。这要求大量特殊的代码,配置,例如InnoDB的next-key锁等。并不是所有的存储引擎都支持基于语句的复制。
如果语句含有任何不确定的函数调用,则可能会导致Master与Slave之间产生不一致的情况。这些函数有:
LOAD_FILE(filename):读取文件,以字符串的形式返回值。
UUID():生成唯一值的函数,128位。
UUID_SHORT():同UUID(),64位。
USER():以utf8字符集返回当前连接MySQL的用户名及主机名。
FOUND_ROWS():返回一个包含limit字句获得的查询总数。
SYSDATE():返回动态执行的时间。
GET_LOCK(str,timeout) :获得一个以字符串命名的锁,且有超时时间。
IS_USED_LOCK(str):检测str命名的锁是否在使用中。
IS_FREE_LOCK(str):检测str命名的锁是否没在使用。
MASTER_POS_WAIT():控制master/slave的同步。
RAND():实现随机数的方法。
RELEASE_LOCK():用来释放因GET_LOCK()获取锁的str。
SLEEP():实现延迟动作的时间的方法。
VERSION():返回MySQL版本信息的函数。
2、基于行的复制(Row-Based Replication)
MySQL增加基于行的复制,在二进制日志中记录下实际数据的改变。这种方式有优点,也有缺点。优点就是可以对任何语句都能正确工作,一些语句的效率更高。主要的缺点就是二进制日志可能会很大,而且不直观,所以,你不能使用mysqlbinlog来查看二进制日志。
对于一些语句,基于记录的复制能够更有效的工作,如:
mysql> INSERT INTO summary_table(col1, col2, sum_col3)
-> SELECTcol1, col2, sum(col3)
-> FROMenormous_table
-> GROUP BYcol1, col2;
假设,只有三种唯一的col1和col2的组合,但是,该查询会扫描原表的许多行,却仅返回三条记录。此时,基于记录的复制效率更高。
另一方面,下面的语句,基于语句的复制更有效:
mysql> UPDATEenormous_table SET col1 = 0;
此时使用基于记录的复制代价会非常高。由于两种方式不能对所有情况都能很好的处理,所以,MySQL 5.1支持在基于语句的复制和基于记录的复制之前动态交换。你可以通过设置session变量binlog_format来进行控制。
3、混合复制
MySQL5.1及其以后的版本推荐使用混合模式的复制,它是根据事件的类型实时的改变binlog的格式。当设置为混合模式时,默认为基于语句的格式,但在特定的情况下它会自动转变为基于行的模式。
当出现如下情况时,混合模式需要切换到基于行的复制:
该语句调用了:
UUID函数;
用户自定义函数(UDFs);
CURRENT_USER或USER函数;
LOAD_FILE函数。
.同一个语句更改了两张或更多包含AUTO_INCREMENT列的表。
.语句中使用了服务器变量。
.存储引擎不允许使用基于语句复制,如:MySQL Cluster引擎。