Documentation Home

16.4.1.33 复制和事务

在同一事务中混合事务性和非事务性语句。  通常,您应该避免在复制环境中同时更新事务性和非事务性表的事务。您还应该避免使用任何访问事务(或临时)和非事务表并写入其中任何一个的语句。

服务器使用这些规则进行二进制日志记录:

  • 如果事务中的初始语句是非事务性的,它们将立即写入二进制日志。事务中剩余的语句被缓存起来,直到事务提交后才写入二进制日志。(如果事务被回滚,缓存的语句只有在进行了不可回滚的非事务性更改时才会写入二进制日志。否则,它们将被丢弃。)

  • 对于基于语句的日志记录,非事务性语句的日志记录受 binlog_direct_non_transactional_updates 系统变量的影响。当此变量为 OFF(默认值)时,日志记录如前所述。当此变量为ON时,将立即对事务中任何位置出现的非事务性语句(不仅仅是初始非事务性语句)进行日志记录。其他语句保存在事务缓存中,并在事务提交时记录下来。 binlog_direct_non_transactional_updates 对行格式或混合格式二进制日志记录没有影响。

事务性、非事务性和混合语句。  要应用这些规则,如果服务器仅更改非事务性表,则服务器将其视为非事务性语句;如果仅更改事务性表,则服务器将其视为事务性语句。引用非事务表和事务表并更新所涉及的任何表的语句被视为混合 语句。(在过去的一些 MySQL 版本中,只有同时更新非事务和事务表的语句才被认为是混合的。)混合语句,如事务语句,在事务提交时被缓存和记录。

如果语句还执行以下任一操作,则更新事务表的混合语句被认为是不安全的:

  • 更新或读取临时表

  • 读取非事务表且事务隔离级别低于 REPEATABLE_READ

如果执行以下任一操作,则在事务中更新事务表之后的混合语句被认为是不安全的:

有关详细信息,请参阅 第 16.2.1.3 节,“二进制日志记录中安全和不安全语句的确定”

笔记

混合语句与混合二进制日志记录格式无关。

在事务混合更新事务和非事务表的情况下,二进制日志中语句的顺序是正确的,并且所有需要的语句都写入二进制日志,即使在 ROLLBACK. 但是,当第二个连接在第一个连接事务完成之前更新非事务表时,语句可能会乱序记录,因为第二个连接更新是在执行后立即写入的,而不管第一个连接正在执行的事务的状态如何联系。

在源和副本上使用不同的存储引擎。  可以使用副本上的非事务性表在源上复制事务性表。例如,您可以将InnoDB源表复制为 MyISAM副本表。但是,如果这样做,如果副本在 BEGIN... COMMIT块的中间停止,则会出现问题,因为副本在块的开头重新启动 BEGIN

MyISAM将源表中的事务复制到副本上的事务表(例如使用 InnoDB存储引擎的表 )也是安全 的。在这种情况下, AUTOCOMMIT=1 复制在源上发出的语句,从而 AUTOCOMMIT在副本上强制执行模式。

当副本的存储引擎类型为非事务性时,应避免混合更新事务性和非事务性表的源上的事务,因为它们会导致源事务性表和副本非事务性表之间的数据不一致。也就是说,此类事务会导致特定于源存储引擎的行为,并可能导致复制不同步。MySQL 目前没有发出关于此的警告,因此在将事务表从源复制到副本上的非事务表时应格外小心。

更改事务中的二进制日志记录格式。 只要事务在进行中, 和系统变量就是只读 的binlog_formatbinlog_checksum

每个事务(包括 autocommit事务)都记录在二进制日志中,就好像它以语句开始, BEGIN 以 a COMMITROLLBACK 语句结束。对于影响使用非事务性存储引擎(例如 MyISAM)的表的语句也是如此。

笔记

有关专门适用于 XA 事务的限制,请参阅第 13.3.7.3 节,“对 XA 事务的限制”