MySQL复制和MEMORY表
内存表不能很好地用于复制。
问题
将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;