使用基于语句的复制,在源上执行的触发器也会在副本上执行。使用基于行的复制,在源上执行的触发器不会在副本上执行。相反,在源上由触发器执行产生的行更改将被复制并应用到副本上。
这种行为是设计使然。如果在基于行的复制下,副本也应用触发器以及它们引起的行的更改,那么更改实际上将在副本上应用两次,导致源和副本上的数据不同。
如果您希望触发器在源和副本上都执行,可能是因为您在源和副本上具有不同的触发器,则必须使用基于语句的复制。但是,要启用副本端的触发器,没有必要完全使用基于语句的复制。仅将那些需要此效果的语句切换到基于语句的复制就足够了,其他情况下可以使用基于行的复制。
使用基于语句的复制,调用触发器(或函数)的语句会导致对 AUTO_INCREMENT
列的更新,不能正确复制。MySQL 9.0 将此类语句标记为不安全。 (Bug #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
参数返回这些值。删除表的所有触发器。
为该表创建一个新的触发器,该触发器调用刚刚创建的存储例程。因此,此触发器的效果与它替换的多个触发器相同。