在 MIXED
日志格式下运行时,服务器会在以下情况下自动从基于语句的日志切换到基于行的日志
当函数包含
UUID()
时。当更新具有
AUTO_INCREMENT
列的一个或多个表时,并调用触发器或存储函数。与所有其他不安全的语句一样,如果binlog_format = STATEMENT
,这会生成警告。有关更多信息,请参见 第 19.5.1.1 节,“复制和 AUTO_INCREMENT”。
当视图的主体需要基于行的复制时,创建视图的语句也会使用它。例如,当创建视图的语句使用
UUID()
函数时,就会发生这种情况。当调用可加载函数时。
当使用
FOUND_ROWS()
或ROW_COUNT()
时。(错误 #12092,错误 #30244)当使用
USER()
、CURRENT_USER()
或CURRENT_USER
时。(错误 #28086)当涉及的表之一是
mysql
数据库中的日志表时。当使用
LOAD_FILE()
函数时。(错误 #39701)当语句引用一个或多个系统变量时。(错误 #31168)
例外。 以下系统变量,当与会话范围一起使用(仅)时,不会导致日志格式切换
有关确定系统变量范围的信息,请参见 第 7.1.9 节,“使用系统变量”。
有关复制如何处理
sql_mode
的信息,请参见 第 19.5.1.40 节,“复制和变量”。
在早于 MySQL 8.0 的版本中,当使用混合二进制日志格式时,如果一个语句是按行记录的,并且执行该语句的会话有任何临时表,那么该会话使用的所有临时表都被删除之前,所有后续语句都被视为不安全的,并以基于行的格式记录。在 MySQL 9.0 中,对临时表的 operations 不会在混合二进制日志格式中记录,并且会话中是否存在临时表对每个语句使用的日志模式没有影响。
如果您尝试使用基于语句的日志执行应该使用基于行的日志写入的语句,则会生成警告。该警告在客户端(在 SHOW WARNINGS
的输出中)和通过 mysqld 错误日志中显示。每次执行此类语句时,都会将警告添加到 SHOW WARNINGS
表中。但是,为了防止日志泛滥,只有为每个客户端会话生成警告的第一个语句才会写入错误日志。
除了上述决定外,各个引擎还可以确定在更新表中的信息时使用的日志格式。各个引擎的日志功能可以定义如下
如果引擎支持基于行的日志记录,则称该引擎为 基于行的日志记录。
如果引擎支持基于语句的日志记录,则称该引擎为 基于语句的日志记录。
给定的存储引擎可以支持任一或两种日志格式。下表列出了每个引擎支持的格式。
存储引擎 | 支持基于行的日志记录 | 支持基于语句的日志记录 |
---|---|---|
ARCHIVE |
是 | 是 |
BLACKHOLE |
是 | 是 |
CSV |
是 | 是 |
EXAMPLE |
是 | 否 |
联合 |
是 | 是 |
堆 |
是 | 是 |
InnoDB |
是 | 当事务隔离级别为 REPEATABLE READ 或 SERIALIZABLE 时为是;否则为否。 |
MyISAM |
是 | 是 |
合并 |
是 | 是 |
NDB |
是 | 否 |
是否记录语句以及使用哪种记录模式取决于语句的类型(安全、不安全或二进制注入)、二进制日志格式(STATEMENT
、ROW
或 MIXED
)以及存储引擎的记录功能(支持语句记录、支持行记录、两者都支持或都不支持)。(二进制注入是指记录必须使用 ROW
格式记录的更改。)
语句可以带或不带警告记录;失败的语句不会记录,但会在日志中生成错误。以下决策表显示了这一点。类型、binlog_format、SLC 和 RLC 列概述了条件,而 错误/警告 和 记录为 列表示相应的操作。 SLC 代表 “支持语句记录”,RLC 代表 “支持行记录”。
类型 | binlog_format |
SLC | RLC | 错误/警告 | 记录为 |
---|---|---|---|---|---|
* | * |
否 | 否 | 错误:无法执行语句:由于至少有一个引擎既不支持行记录也不支持语句记录,因此无法执行二进制日志记录。 | - |
安全 | STATEMENT |
是 | 否 | - | STATEMENT |
安全 | MIXED |
是 | 否 | - | STATEMENT |
安全 | ROW |
是 | 否 | 错误:无法执行语句:由于 BINLOG_FORMAT = ROW 并且至少有一个表使用不支持基于行的日志记录的存储引擎,因此无法执行二进制日志记录。 |
- |
不安全 | STATEMENT |
是 | 否 | 警告:不安全语句以语句格式记录在二进制日志中,因为 BINLOG_FORMAT = STATEMENT |
STATEMENT |
不安全 | MIXED |
是 | 否 | 错误:无法执行语句:当存储引擎仅限于基于语句的日志记录时,即使 BINLOG_FORMAT = MIXED ,也不可能执行不安全语句的二进制日志记录。 |
- |
不安全 | ROW |
是 | 否 | 错误:无法执行语句:由于 BINLOG_FORMAT = ROW 并且至少有一个表使用不支持基于行的日志记录的存储引擎,因此无法执行二进制日志记录。 |
- |
行注入 | STATEMENT |
是 | 否 | 错误:无法执行行注入:由于至少有一个表使用不支持基于行的日志记录的存储引擎,因此无法执行二进制日志记录。 | - |
行注入 | MIXED |
是 | 否 | 错误:无法执行行注入:由于至少有一个表使用不支持基于行的日志记录的存储引擎,因此无法执行二进制日志记录。 | - |
行注入 | ROW |
是 | 否 | 错误:无法执行行注入:由于至少有一个表使用不支持基于行的日志记录的存储引擎,因此无法执行二进制日志记录。 | - |
安全 | STATEMENT |
否 | 是 | 错误:无法执行语句:由于 BINLOG_FORMAT = STATEMENT 并且至少有一个表使用不支持基于语句的日志记录的存储引擎,因此无法执行二进制日志记录。 |
- |
安全 | MIXED |
否 | 是 | - | ROW |
安全 | ROW |
否 | 是 | - | ROW |
不安全 | STATEMENT |
否 | 是 | 错误:无法执行语句:由于 BINLOG_FORMAT = STATEMENT 并且至少有一个表使用不支持基于语句的日志记录的存储引擎,因此无法执行二进制日志记录。 |
- |
不安全 | MIXED |
否 | 是 | - | ROW |
不安全 | ROW |
否 | 是 | - | ROW |
行注入 | STATEMENT |
否 | 是 | 错误:无法执行行注入:由于 BINLOG_FORMAT = STATEMENT ,因此无法执行二进制日志记录。 |
- |
行注入 | MIXED |
否 | 是 | - | ROW |
行注入 | ROW |
否 | 是 | - | ROW |
安全 | STATEMENT |
是 | 是 | - | STATEMENT |
安全 | MIXED |
是 | 是 | - | STATEMENT |
安全 | ROW |
是 | 是 | - | ROW |
不安全 | STATEMENT |
是 | 是 | 警告:不安全语句以语句格式记录在二进制日志中,因为 BINLOG_FORMAT = STATEMENT 。 |
STATEMENT |
不安全 | MIXED |
是 | 是 | - | ROW |
不安全 | ROW |
是 | 是 | - | ROW |
行注入 | STATEMENT |
是 | 是 | 错误:无法执行行注入:由于 BINLOG_FORMAT = STATEMENT ,因此无法执行二进制日志记录。 |
- |
行注入 | MIXED |
是 | 是 | - | ROW |
行注入 | ROW |
是 | 是 | - | ROW |
当确定过程产生警告时,会生成一个标准的 MySQL 警告(可以使用 SHOW WARNINGS
获取)。这些信息也会写入 mysqld 错误日志。为了防止日志泛滥,每个客户端连接每个错误实例只记录一个错误。日志消息包含尝试执行的 SQL 语句。
如果副本的 log_error_verbosity
设置为显示警告,则副本会将消息打印到错误日志中,以提供有关其状态的信息,例如它开始作业的二进制日志和中继日志坐标、切换到另一个中继日志的时间、断开连接后重新连接的时间、不适合基于语句的日志记录的语句等等。