下面我们来复现下:

5.5的表现

  1. mysql> alter table t2 drop c2;
  2. mysql> alter table t2 drop foreign key idx1;
  3. ERROR 1025 (HY000): Error on rename of './test/t2' to './test/#sql2-78fd-780371' (errno: 152)

5.6的表现

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

  1. mysql_alter_table
  2. |===>innobase_check_foreign_key_index

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

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

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

我们来看一个外键相关的bug77467

  1. Alter table reply
  2. drop index userId,

我们来看看5.5的流程:

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

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

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