天天看点

MySQL · 答疑解惑 · 外键删除bug分析

下面我们来复现下:

5.5的表现

5.6的表现

很明显5.6的报错信息更精确些,5.5的报错太不人性化了,容易造成误解。

它们差别在于5.6的报错处理在语义分析阶段,精准的定位了错误信息。

而5.5的报错处理在执行阶段。

我们先来看看5.5的执行流程:

<code>dict_load_foreigns</code>:这个函数由于承担的责任太多,只要发现错误,就笼统的抛出<code>error on rename of 'xxxx' to 'xxxx' (errno: xxx)</code>的错误.

bug中这个ddl虽然执行失败了,但实际上foreign key reply_ibfk_2被删除了。这个bug在单机环境下影响不大,但在主备环境下由于ddl执行失败并没有记binlog,从而导致主备表结构不一致。这个bug只出现在5.6以前的版本中,5.6是ok的

我们来看看5.5的流程:

出错回滚之前的修改,预期是回滚删除外键reply_ibfk_2,但是删除外键reply_ibfk_2操作在第一次<code>mysql_rename_table</code>中,属于一个事务,而回滚操作在第二次<code>mysql_rename_table</code>中,属于另一个事务,因此回滚没有成功。

那么5.6为什么没有出现这种错误呢?5.6在语义分析的时候就发现错误,还没来得及删外键就已经报错返回了。

5.5修复方法,将删外键的操作放到第二次<code>mysql_rename_table</code>中进行,如果出现错误就可以顺利的回滚了。当然,还是5.6的做法比较好。

继续阅读