#### 17.5.1.36复制和触发器

[](<>)[](<>)

使用基于语句的复制，在源上执行的触发器也在副本上执行。对于基于行的复制，在源上执行的触发器不会在副本上执行。相反，源上因触发器执行而产生的行更改会被复制并应用到副本上。

这种行为是故意的。如果在基于行的复制下，复制副本应用了触发器以及由它们引起的行更改，那么这些更改实际上会在复制副本上应用两次，从而导致源和复制副本上的数据不同。

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

一种调用触发器（或函数）的语句，该触发器（或函数）会导致对`自动增量`未使用基于语句的复制正确复制列。MySQL 8.0将此类语句标记为不安全。（Bug#45677）

触发器可以具有用于不同触发器事件组合的触发器([`插入`](insert.html),[`使现代化`](update.html),[`删去`](delete.html))行动时间(`之前`,`之后`)，并且允许多个触发器。

为简洁起见，“多个触发器”是“具有相同触发事件和动作时间的多个触发器”的缩写

**升级。**MySQL 5.7之前的版本不支持多个触发器。如果升级使用MySQL 5.7之前版本的复制拓扑中的服务器，请先升级副本，然后升级源。如果升级的复制源服务器仍有使用不支持多个触发器的MySQL版本的旧副本，则如果在源服务器上为已具有相同触发器事件和操作时间的触发器的表创建触发器，则这些副本上会发生错误。

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

-   对于每个具有触发器的表，所有触发器定义都位于`.训练`整理桌子。但是，如果有多个触发器具有相同的触发器事件和操作时间，则服务器在触发器事件发生时只执行其中一个触发器。有关`.训练`文件，请参阅MySQL Server Doxygen文档中的表触发器存储部分，可在<https://dev.mysql.com/doc/index-other.html>.

-   如果在降级后添加或删除了表的触发器，服务器将重写表的`.训练`文件重写后的文件在触发器事件和动作时间的每个组合中只保留一个触发器；其他人都迷路了。

    为了避免这些问题，在降级之前修改触发器。对于每种触发器事件和动作时间组合都有多个触发器的每个表，将每一组触发器转换为一个触发器，如下所示：

1.  对于每个触发器，创建一个包含触发器中所有代码的存储例程。使用`新`和`古老的`可以使用参数传递给例程。如果触发器需要来自代码的单个结果值，可以将代码放入存储函数中，并让函数返回该值。如果触发器需要代码中的多个结果值，可以将代码放入存储过程中，并使用`出来`参数。

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

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