1. binlog 日志格式

binlog 日志有两种格式,statement-based 和 row-based。 当使用 statement-based 方式,Master 将 SQL 语句写入binary log 文件,slave 获取到 binary log 文件以后,执行其中的 SQL 语句。 当使用 row-based 方式,Master 会将表中每一行的修改都记录到 binary log 文件中,slave 获取到 binary log 文件后逐行实现这些修改。 你也可以配置 MySQL 混合使用这两种方式(MIXED FORMAT),即同时使用 statement-based 和 row-based ,在记录日志时,MySQL 会选择最适合的方式来记录日志。当使用混合日志时,statement-based 是默认的日志格式,但是在某些情况下会自动切换为 row-based 格式来记录日志,具体格式由使用的存储引擎和执行的语句共同决定。具体可参见:Mixed Binary Logging Format

Note: MySQL 5.7.7 之前,默认的格式是 statement-based,5.7.7及以后的版本,row-based 是默认的日志格式。

2. Statement-Based 和 Row-Based 的优点和缺点

每种日志格式都有优点和缺点,对于大部分用户,混合模式(MIXED FORMAT) 也许是最好的(provide the best combination of data integrity and perfomance)。

1. Statement-Based 优点:

久经验证的技术 写入 log 文件的数据更少,同时恢复数据时也更快。 log 文件包含所有的改变数据库的语句,可以用来审计数据库(audit database)。

2. Statement-Based 缺点:

不是所有修改数据的语句都可以使用 statement-based 方式记录日志,一些不确定的操作就很难使用 statement-based 方式记录。比如下面的一些 DML 语句: 一个 DML 语句如果依赖不确定的 UDF 或存储方法(stored program),就不能使用 Statement-Based 方式记录,因为这个 DML 语句的执行结果会受这些不确定的 UDF 或存储方法的影响。 DELETE 和 UPDATE 语句如果使用了 LIMIT 但是没有使用 ORDER BY,那么结果也是不确定的,也不能使用 Statement-Based 方式记录日志。Replication and LIMIT 使用了下面方法的语句不能使用 Statement-Based 方式记录日志: LOAD_FILE() UUID(), UUID_SHORT() USER() FOUND_ROWS() SYSDATE() (除非Master 和 Slave 在启动时都添加了 --sysdate-is-now 选项) GET_LOCK() IS_FREE_LOCK() IS_USER_LOCK() MASTER_POS_WAIT() RAND() RELEASE_LOCK() SLEEP() VERSION() 其他的函数都可以使用 Statement-Based 方式记录日志,包括 NOW() 之类的。详情可参见:Replication and System Functions INSERT ... SELECT 语句使用 Statement-Based 方式比 Row-Based 方式需要更多的行级锁。 UPDATE 语句需要全表扫描时(where 条件的字段未设置索引),Statement-Based 方式需要更多的锁(译者注:貌似需要锁全表) 对于 InnoDB 引擎,一个带有 AUTO_INCREMENT 的 INSERT 语句会阻塞其他的 INSERT 语句。 Stored functions execute with the same NOW() value as the calling statement. However, this is not true of stored procedures. 使用 Statement-Based 方式记录日志,语句里的 NOW() 在主从两台机器上会得到相同的值, Master 和 Slave 上的表结构必须完全一致。Replication with Differing Table Definitions on Master and Slave

3. Row-Based 优点:

所有的改变都可以写入到日志,这也是最安全的方式。 对于任何 INSERT/UPDATE/DELETE 操作,Row-Based 方式需要更少的行锁。 对于下面的语句,Row-Based 方式使得 Master 需要更少的行锁,因此可以获得更高的性能:(这个有点看不懂,跟 Master 有什么关系?) INSERT ... SELECT 带有 AUTO_INCREMENT 的 INSERT UPDATE/DELETE 语句的 where 条件字段没有设置索引 Note: 更新数据库信息的语句,比如 GRANT,REVOKE 和对触发器、视图、存储程序(包括存储过程)的操作,都是使用 Statement-Based 方式写日志。(是不是 DDL 语句都是使用 Statement-Based 方式呢?)

4. Row-Based 缺点:

Row-Based 方式会使得更多的数据被写入到日志文件,因为它会将所有改变的行都写入日志。另外,binlog 日志文件在写入日志的时候会被锁住,如果数据太多可能会导致性能问题。可以添加参数 binlog_row_image=minimal 来减少这个缺点。 如果一个确定的 UDF 产生了大量的 BLOB 数据,那么用 Row-Based 方式记录日志并恢复数据需要花费更多的时间。 For tables using the MyISAM storage engine, a stronger lock is required on the slave for INSERT statements when applying them as row-based events to the binary log than when applying them as statements. This means that concurrent inserts on MyISAM tables are not supported when using row-based replication