在 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.39 节,“复制和变量”。
在早于 MySQL 8.0 的版本中,当使用混合二进制日志格式时,如果语句是通过行记录的,并且执行该语句的会话有任何临时表,则所有后续语句都被视为不安全,并以基于行的格式记录,直到该会话使用的所有临时表都被删除。在 MySQL 8.4 中,对临时表的 operations 不会记录在混合二进制日志格式中,并且会话中存在临时表不会影响用于每个语句的日志模式。
如果您尝试使用基于语句的日志执行应该使用基于行的日志写入的语句,则会生成警告。该警告会在客户端(在 SHOW WARNINGS
的输出中)和通过 mysqld 错误日志显示。每次执行此类语句时,都会将警告添加到 SHOW WARNINGS
表中。但是,为了防止日志泛滥,每个客户端会话中仅将第一个生成警告的语句写入错误日志。
除了上述决定之外,各个引擎还可以确定更新表中信息时使用的日志格式。各个引擎的日志功能可以定义如下
如果引擎支持基于行的日志,则该引擎被称为 支持基于行的日志。
如果引擎支持基于语句的日志,则该引擎被称为 支持基于语句的日志。
给定的存储引擎可以支持任何一种或两种日志格式。下表列出了每个引擎支持的格式。
存储引擎 | 支持基于行的日志 | 支持基于语句的日志 |
---|---|---|
ARCHIVE |
是 | 是 |
BLACKHOLE |
是 | 是 |
CSV |
是 | 是 |
EXAMPLE |
是 | 否 |
FEDERATED |
是 | 是 |
HEAP |
是 | 是 |
InnoDB |
是 | 如果事务隔离级别为REPEATABLE READ 或SERIALIZABLE ,则为“是”,否则为“否”。 |
MyISAM |
是 | 是 |
MERGE |
是 | 是 |
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
设置为显示警告,则副本会向错误日志打印消息,以提供有关其状态的信息,例如它开始工作时的二进制日志和中继日志坐标、切换到另一个中继日志的时间、断开连接后重新连接的时间、不适合基于语句的日志记录的语句等等。