在基于语句的复制中,在源上执行的触发器也会在副本上执行。在基于行的复制中,在源上执行的触发器不会在副本上执行。相反,源上触发器执行导致的行更改会复制并应用到副本上。
此行为是设计使然。如果在基于行的复制中,副本也应用了触发器以及它们引起的行的更改,则更改实际上会在副本上应用两次,导致源和副本上的数据不同。
如果您希望触发器在源和副本上都执行,可能是因为您在源和副本上有不同的触发器,则必须使用基于语句的复制。但是,要启用副本端的触发器,不需要完全使用基于语句的复制。仅在需要此效果的语句上切换到基于语句的复制,而在其余时间使用基于行的复制就足够了。
使用基于语句的复制无法正确复制调用触发器(或函数)的语句,该语句会导致对 AUTO_INCREMENT
列进行更新。MySQL 8.4 将此类语句标记为不安全。(错误 #45677)
触发器可以具有触发器事件(INSERT
、UPDATE
、DELETE
)和操作时间(BEFORE
、AFTER
)的不同组合,并且允许使用多个触发器。
为了简洁起见,这里 “多个触发器” 是 “具有相同触发器事件和操作时间的多个触发器。” 的简写。
升级。 在早于 MySQL 5.7 的版本中不支持多个触发器。如果您升级使用早于 MySQL 5.7 的版本的复制拓扑中的服务器,请先升级副本,然后再升级源。如果升级后的复制源服务器仍然具有使用不支持多个触发器的 MySQL 版本的旧副本,则如果在源上为已具有具有相同触发器事件和操作时间的触发器的表创建触发器,则这些副本上会发生错误。
降级。 如果您将支持多个触发器的服务器降级到不支持多个触发器的旧版本,则降级会产生以下影响
对于具有触发器的每个表,所有触发器定义都位于表的
.TRG
文件中。但是,如果有多个触发器具有相同的触发器事件和操作时间,则服务器在触发器事件发生时仅执行其中一个。有关.TRG
文件的信息,请参见 MySQL 服务器 Doxygen 文档的“表触发器存储”部分,该文档可从 https://dev.mysqlserver.cn/doc/index-other.html 获取。如果在降级后为表添加或删除触发器,则服务器会重写表的
.TRG
文件。重写后的文件只保留每个触发器事件和操作时间组合的一个触发器;其他触发器会丢失。
为了避免这些问题,请在降级之前修改您的触发器。对于每个具有多个触发器(每个触发器事件和操作时间组合)的表,请将每个此类触发器集转换为单个触发器,如下所示
对于每个触发器,创建一个包含触发器中所有代码的存储例程。使用
NEW
和OLD
访问的值可以通过参数传递给例程。如果触发器需要代码中的单个结果值,您可以将代码放在存储函数中,并让函数返回值。如果触发器需要代码中的多个结果值,您可以将代码放在存储过程中,并使用OUT
参数返回值。删除表的所有触发器。
为表创建一个新的触发器,该触发器调用刚刚创建的存储例程。因此,此触发器的效果与它替换的多个触发器相同。