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
原文:
Replication Formats
Advantages and Disadvantages of Statement-Based and Row-Based Replication