Documentation Home

16.4.1.34 复制和触发器

使用基于语句的复制,在源上执行的触发器也会在副本上执行。使用基于行的复制,在源上执行的触发器不会在副本上执行。相反,触发器执行导致的源上的行更改被复制并应用于副本。

此行为是设计使然。如果在基于行的复制下,副本应用了触发器以及由它们引起的行更改,则这些更改实际上会在副本上应用两次,从而导致源和副本上的数据不同。

如果您希望触发器在源和副本上都执行,可能是因为您在源和副本上有不同的触发器,您必须使用基于语句的复制。但是,要启用副本端触发器,没有必要专门使用基于语句的复制。仅对那些需要这种效果的语句切换到基于语句的复制就足够了,而在其余时间使用基于行的复制。

AUTO_INCREMENT使用基于语句的复制无法正确复制 调用导致更新列的触发器(或函数)的语句。MySQL 5.7 将此类语句标记为不安全。(漏洞 #45677)

一个触发器可以有触发事件(INSERT, UPDATE, DELETE)和动作时间(BEFORE, AFTER)的不同组合的触发器,但在 MySQL 5.7.2 之前不能有多个具有相同触发事件和动作时间的触发器。MySQL 5.7.2 取消了这个限制,允许多个触发器。此更改对升级和降级具有复制影响。

为了简洁起见,这里的多个触发器”是具有相同触发事件和动作时间的多个触发器”的简写。

升级。假设您将不支持多触发器的旧服务器升级到 MySQL 5.7.2 或更高版本。如果新服务器是复制源服务器并且具有不支持多个触发器的旧副本,则如果在源上为已经具有具有相同触发器事件和操作时间的触发器的表创建触发器,则会在这些副本上发生错误. 为避免此问题,请先升级副本,然后再升级源。

降级。如果将支持多个触发器的服务器降级为不支持的旧版本,则降级会产生以下影响:

  • 对于具有触发器的每个表,所有触发器定义都保留在.TRG该表的文件中。但是,如果有多个触发器具有相同的触发事件和动作时间,则服务器在触发事件发生时只执行其中一个。有关 .TRG文件的信息,请参阅 MySQL Server Doxygen 文档的表触发器存储部分,该文档位于https://mysql.net.cn/doc/index-other.html

  • 如果在降级后添加或删除表的触发器,服务器将重写表的 .TRG文件。重写的文件只保留每个触发事件和动作时间组合的触发;其他人都迷路了。

为避免这些问题,请在降级之前修改您的触发器。对于每个触发器事件和操作时间的组合都有多个触发器的每个表,将每个这样的触发器集转换为单个触发器,如下所示:

  1. 对于每个触发器,创建一个包含触发器中所有代码的存储例程。NEW使用和访问的值可以 OLD使用参数传递给例程。如果触发器需要来自代码的单个结果值,您可以将代码放在存储函数中并让函数返回该值。如果触发器需要来自代码的多个结果值,您可以将代码放在存储过程中并使用OUT参数返回值。

  2. 删除表的所有触发器。

  3. 为调用刚刚创建的存储例程的表创建一个新触发器。因此,此触发器的效果与其替换的多个触发器相同。