在同一事务中混合事务型语句和非事务型语句. 在 MySQL 9.0(及更高版本)中,更新事务型表和非事务型或不可组合表的混合事务已被弃用,并会导致将弃用警告写入客户端和错误日志。 在 MySQL 9.0 中,只有 InnoDB
和 BLACKHOLE
存储引擎是事务型和可组合的;NDBCLUSTER
是事务型但不可组合的。 这意味着,不会 触发弃用警告的唯一存储引擎组合是这里列出的那些
InnoDB
和BLACKHOLE
MyISAM
和Merge
performance_schema
和任何其他存储引擎TempTable
和任何其他存储引擎
一般来说,您应该避免在复制环境中更新事务型表和非事务型表的混合事务。 您还应该避免使用访问事务型(或临时)表和非事务型表并写入其中任何一个的语句。
服务器使用以下规则进行二进制日志记录
如果事务中的初始语句是非事务型的,它们会立即写入二进制日志。 事务中的剩余语句将被缓存,直到事务提交后才会写入二进制日志。(如果事务回滚,只有在它们进行无法回滚的非事务型更改时才会将缓存的语句写入二进制日志。 否则,它们将被丢弃。)
对于基于语句的日志记录,非事务型语句的日志记录受
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 事务的限制”。