MySQL复制和MEMORY表

时间:2020-03-21 11:42:16  来源:igfitidea点击:

内存表不能很好地用于复制。

问题

将MySQL服务器从5.6升级到5.7后,我们注意到主/从复制开始失败,并出现以下错误:

无法在表my_database.my_table上执行Delete_rows事件;在" my_table"中找不到记录,错误代码:1032;处理程序错误HA_ERR_KEY_NOT_FOUND;活动的主日志bin-log.003023,end_log_pos 552195868

如果重新启动从属服务器,则会丢失MEMORY表的内容,并且MySQL复制会中断。

努力寻求解决方案

MySQL Binary Logging:MySQL 5.6与MySQL 5.7

在MySQL 5.7.7之前,默认的binlog_format是STATEMENT。
这就是我们升级之前使用的方式。

在MySQL 5.7.7和更高版本中,默认值为ROW。
这就是升级后的内容。

现在,在MySQL 5.6上,STATEMENT复制通常会继续运行,并且表的内容有所不同,因为只要语句在从属服务器上产生相同的结果,就会进行一些检查。

但是,ROW复制将抱怨UPDATE或者DELETE操作不存在ROW。

解决方法:使用SQL_SLAVE_SKIP_COUNTER

当复制由于找不到行而不能删除而中断时,我们可以执行以下操作:

STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
START SLAVE;

这将跳过有问题的语句并恢复复制。
小心点!就我们而言,这很好,因为应用程序逻辑使得可以安全地丢失MEMORY表的内容(有问题的表用于缓存)。

请注意,这种方法不是解决方案,因为一旦有另一个影响MEMORY表的update或者delete语句,我们的联系就会被破坏。

解决方案:不复制MEMORY表

如果我们不需要在从属服务器上使用MEMORY表,则可以停止复制它们。

我们需要创建一个复制过滤器,以防止从属线程复制任何表都匹配给定通配符模式的语句。

在我们的情况下,我们将使用以下内容:

--replicate-wild-ignore-table="my_database.my_table"

如果我们有多个存在此问题的数据库,则可以使用通配符:

--replicate-wild-ignore-table="%.my_table"

上面的内容不会复制使用数据库名称为任何表且该表与" my_table"匹配的表的更新。

这也可以随时进行:

STOP SLAVE;
CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('%.my_table');
START SLAVE;