服务器使用多种记录格式在二进制日志中记录信息。确切的格式取决于正在使用的MySQL版本。

记录模式也会由正在使用的存储引擎设置或限制。这有助于消除在使用不同存储引擎的主服务器和从服务器之间复制某些语句时的问题。

使用基于语句的复制时,复制非确定性语句可能存在问题。在决定给定语句是否对基于语句的复制是安全的时,MySQL决定它是否可以保证可以使用基于语句的日志记录来复制语句。如果MySQL无法做出这种保证,它会将该语句标记为可能不可靠并发出警告,Statement模式二进制日志可能无法安全地记录此语句。

一、Statement 基于语句模式

MySQL中的复制功能最初是基于从主机到从机的SQL语句的传播。这被称为基于语句的日志记录。您可以通过启动服务器来使用此格式 –binlog-format=STATEMENT。

优点:日志的记录量少,节省了I/O以及存储资源,提高性能。

缺点:必须记录每条语句在执行时的上下文信息,以保证所有语句在slave端被执行时数据一致。不少情况下会造成mysql复制数据混乱。

如:sleep()函数在有些版本中就不能被正确复制,在存储过程中使用了last_insert_id()函数,可能会使slave和master上得到不一致的id等等。

二、Row 基于行模式

在基于行的日志记录中,主服务器将事件写入二进制日志,以指示单个表行如何受到影响。因此,表总是使用主键来确保行可以被有效识别,这一点很重要。您可以通过启动该服务器来使服务器使用基于行的日志记录 –binlog-format=ROW。

优点:row的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。

缺点:当一条批量修改的SQL执行过程中,会产生大量的日志内容。

三、Mixed 混合模式

混合记录。对于混合日志记录,缺省情况下使用基于语句的日志记录,但在某些情况下,日志记录模式会自动切换为基于行的。您可以通过使用该选项 启动mysqld来使MySQL明确使用混合日志记录–binlog-format=MIXED。

四、设置二进制日志模式

您可以通过启动MySQL服务器来显式选择二进制日志记录格式。记录格式也可以在运行时切换。设置binlog_format系统变量的全局值:

mysql> SET GLOBAL binlog_format = 'STATEMENT';
mysql> SET GLOBAL binlog_format = 'ROW';
mysql>SET GLOBAL binlog_format = 'MIXED';
单个客户端可以通过设置会话值来控制自己的语句的日志格式 binlog_format:
mysql> SET SESSION binlog_format = 'STATEMENT';
mysql> SET SESSION binlog_format = 'ROW';
mysql>SET SESSION binlog_format = 'MIXED';

4.1、二进制日志设置补充

每个MySQL服务都可以设置自己的binlog_format,并且只能设置自己的binlog_format。

也就是在主从复制过程中,设置Master的binlog_format并不会影响到Slave服务。

更改全局(GLOBAL)或会话(SESSION) binlog_format值,您必须具有该SUPER权限。

4.2、客户端可能希望按每个会话设置二进制日志记录的原因有几个

会对数据库进行很多小改动的会话可能需要使用基于行的日志记录。

执行与WHERE子句中的许多行匹配的更新的会话 可能需要使用基于语句的日志记录,因为记录少数几条语句比多行更有效。

某些语句需要在主服务器上执行很多时间,但会导致只修改几行。因此使用基于行的日志记录复制它们可能是有益的。

4.3、在主从复制运行时无法切换格式是存在例外情况的

从存储的函数或触发器中

如果NDB存储引擎已启用

如果会话当前处于基于行的复制模式并且已打开临时表

五、混合二进制日志格式

以MIXED日志格式运行时,服务器在以下情况下自动从基于语句的行切换到基于行的日志记录:

1、当一个函数包含时 UUID()。

2、当一个或多个包含 AUTO_INCREMENT列的表被更新并且触发器或存储函数被调用时。

像所有其他不安全的语句一样,这会在出现警告时生成警告 binlog_format = STATEMENT。

3、当视图的主体需要基于行的复制时,创建视图的语句也会使用它。

例如,创建视图的语句使用该UUID()函数时会发生这种情况 。

4、涉及到UDF的调用时。

5、如果语句按行记录,并且执行该语句的会话具有任何临时表,则按行记录将用于所有后续语句(除访问临时表的那些语句外),直到删除该会话使用的所有临时表为止。

无论是否实际记录临时表,情况都是如此。

使用基于行的格式不能记录临时表; 因此,一旦使用基于行的日志记录,则使用该表的所有后续语句都是不安全的。服务器通过将会话期间执行的所有语句视为不安全,直到会话不再保存任何临时表,将近似于此条件。

6、FOUND_ROWS()或 ROW_COUNT()使用。

7、USER(),, CURRENT_USER()还是 CURRENT_USER被使用。

8、当一个语句引用一个或多个系统变量时。

例外。 以下系统变量与会话作用域(仅)一起使用时,不会导致记录格式切换:

auto_increment_increment
auto_increment_offset
character_set_client
character_set_connection
character_set_database
character_set_server
collation_connection
collation_database
collation_server
foreign_key_checks
identity
last_insert_id
lc_time_names
pseudo_thread_id
sql_auto_is_null
time_zone
timestamp
unique_checks

9、当涉及的其中一个表是mysql数据库中的日志表时 。

10、当使用该LOAD_FILE()功能时。

注意

如果您尝试使用基于语句的日志记录来执行语句,则应该使用基于行的日志记录来生成警告。该警告显示在客户端(在输出中SHOW WARNINGS)和mysqld错误日志中。SHOW WARNINGS 每次执行这样的语句时,都会向表中添加警告。但是,只有为每个客户端会话生成警告的第一条语句才会写入错误日志以防止日志泛滥。

六、存储引擎因素

除了修改数据的语句会影响到二进制日志的记录方式;不同的存储引擎也会对二进制日志模式造成影响。

如果引擎支持基于行的日志记录,则该引擎被称为行日志记录功能。

如果一个引擎支持基于语句的日志记录,那么这个引擎就被说成是语句记录功能。

给定的存储引擎可以支持一种或两种日志格式。

修改语句被记录的情况分为:正常语句记录并无警告、失败语句记录并输出错误到一般日志2