19.5.1.35 复制和事务
在同一个事务中混合事务和非事务语句。 通常情况下,您应该避免在复制环境中更新事务和非事务表的同一个事务。您也应该避免使用任何访问事务表(或临时表)和非事务表,并对其中任何表进行写入的语句。
服务器使用以下规则记录二进制日志:
-
如果事务的初始语句是非事务语句,它们将立即写入到二进制日志中。事务中的其余语句将被缓存,不会写入到二进制日志中,直到事务提交。 (如果事务回滚,缓存的语句将写入到二进制日志中,只有当它们不能回滚的非事务更改时。否则,它们将被丢弃。)
-
对于语句级别的记录,非事务语句的记录受
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事务的限制”。