在同一个事务中混合事务性语句和非事务性语句。 一般情况下,应避免在复制环境中更新事务性表和非事务性表的事务。还应避免使用访问事务性表(或临时表)和非事务性表并写入其中任何一个的语句。
服务器使用以下规则进行二进制日志记录
如果事务中的初始语句是非事务性的,则立即将它们写入二进制日志。事务中的剩余语句将被缓存,并且不会写入二进制日志,直到事务提交。(如果事务回滚,只有在它们进行无法回滚的非事务性更改时,才会将缓存的语句写入二进制日志。否则,它们将被丢弃。)
对于基于语句的日志记录,非事务性语句的日志记录受
binlog_direct_non_transactional_updates
系统变量的影响。当此变量为OFF
(默认值)时,日志记录与上述描述相同。当此变量为ON
时,在事务中的任何位置(不仅仅是初始非事务性语句)发生的非事务性语句都会立即进行日志记录。其他语句将保留在事务缓存中,并在事务提交时进行日志记录。binlog_direct_non_transactional_updates
对行格式或混合格式的二进制日志记录没有影响。
事务性、非事务性和混合语句。 为了应用这些规则,服务器会将一个语句视为非事务性,如果它只更改非事务性表,而将其视为事务性,如果它只更改事务性表。引用非事务性表和事务性表并更新任何所涉及表的语句被视为“混合”语句。混合语句,就像事务性语句一样,会被缓存并在事务提交时进行日志记录。
更新事务性表的混合语句,如果该语句还执行以下任一操作,则被视为不安全
更新或读取临时表
读取非事务性表,并且事务隔离级别低于 REPEATABLE_READ
在事务中更新事务性表之后执行的混合语句,如果它执行以下任一操作,则被视为不安全
更新任何表并从任何临时表中读取
更新非事务性表,并且
binlog_direct_non_transactional_updates
为 OFF
有关更多信息,请参见第 19.2.1.3 节,“确定二进制日志记录中的安全和不安全语句”。
混合语句与混合二进制日志记录格式无关。
在事务混合更新事务表和非事务表的情况下,二进制日志中语句的顺序是正确的,即使在出现ROLLBACK
时,所有必要的语句也会写入二进制日志。但是,当第二个连接在第一个连接事务完成之前更新非事务表时,语句可能会以乱序方式记录,因为第二个连接更新会在执行后立即写入,而与第一个连接执行的事务状态无关。
在源和副本上使用不同的存储引擎。 可以使用副本上的非事务表复制源上的事务表。例如,可以将 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 事务限制”。