在同一事务中混合事务性和非事务性语句。 一般来说,在复制环境中,您应该避免在同一事务中更新事务性和非事务性表。
服务器使用以下规则进行二进制日志记录:
-
如果事务的初始语句是非事务性的,它们将立即写入二进制日志。事务中的剩余语句将被缓存,直到事务提交时才写入二进制日志。(如果事务回滚,缓存的语句将仅在它们对非事务性表进行不可回滚的更改时写入二进制日志。否则,它们将被丢弃。)
-
对于基于语句的日志记录,非事务性语句的日志记录受到
binlog_direct_non_transactional_updates
系统变量的影响。当该变量为OFF
(默认)时,日志记录如上所述。当该变量为ON
时,对于事务中的任何位置的非事务性语句,日志记录将立即发生。其他语句将被缓存在事务缓存中,并在事务提交时写入日志。binlog_direct_non_transactional_updates
对行格式或混合格式的二进制日志记录无效。
事务性、非事务性和混合语句。 为了应用这些规则,服务器将语句视为非事务性语句,如果它仅更改非事务性表;将语句视为事务性语句,如果它仅更改事务性表。一个语句如果引用了非事务性和事务性表,并更新了其中任何一个表,则被视为“混合”语句。混合语句,如事务性语句一样,将被缓存并在事务提交时写入日志。
如果一个混合语句更新了事务性表,它将被视为不安全的,如果语句还执行以下任何操作:
-
更新或读取临时表
-
读取非事务性表,并且事务隔离级别小于 REPEATABLE_READ
在事务中更新事务性表后,一个混合语句如果执行以下任何操作,将被视为不安全的:
-
更新任何表并从任何临时表读取
-
更新非事务性表,并且
binlog_direct_non_transactional_updates
为 OFF
有关更多信息,请参阅 第 19.2.1.3 节,“二进制日志记录中的安全和不安全语句确定”。
混合语句与混合二进制日志格式无关。
在事务中混合更新事务性和非事务性表时,二进制日志中的语句顺序正确,并且所有需要的语句都会被写入二进制日志,即使在回滚时也是如此。然而,当第二个连接在第一个连接事务完成之前更新非事务性表时,语句可能会以错误的顺序被写入日志,因为第二个连接的更新将立即被写入日志,而不管第一个连接的事务状态如何。
在源和副本上使用不同的存储引擎。 可以在源上使用事务性表,并在副本上使用非事务性表来复制它们。例如,可以将 InnoDB
源表复制到 MyISAM
副本表中。然而,如果这样做,并且副本在 BEGIN
... COMMIT
块中停止时,会出现问题,因为副本将从 BEGIN
块的开始处重新启动。
它也可以安全地从MyISAM
表在源上复制事务到事务表,如使用InnoDB
存储引擎的表在副本上。在这种情况下,在源上发出AUTOCOMMIT=1
语句将被复制,从而在副本上强制执行AUTOCOMMIT
模式。
当副本的存储引擎类型为非事务时,源上的事务中混合更新事务和非事务表应该避免,因为它们可能会导致源事务表和副本非事务表之间的数据不一致。也就是说,这些事务可能会导致源存储引擎特定的行为,可能会使复制脱机。 MySQL 不会发出警告,因此在从源事务表复制到副本非事务表时需要格外小心。
在事务中更改二进制日志格式。 在事务进行中,binlog_format
和binlog_checksum
系统变量是只读的。
每个事务(包括autocommit
事务)都将被记录在二进制日志中,好像它以BEGIN
语句开始,以COMMIT
或ROLLBACK
语句结束。即使是影响非事务存储引擎(如MyISAM
)的表也是如此。
有关 XA 事务的限制,请参阅第 15.3.8.3 节,“XA 事务限制”。