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