下面我们来复现下:
5.5的表现
mysql> alter table t2 drop c2;
mysql> alter table t2 drop foreign key idx1;
ERROR 1025 (HY000): Error on rename of './test/t2' to './test/#sql2-78fd-780371' (errno: 152)
5.6的表现
很明显5.6的报错信息更精确些,5.5的报错太不人性化了,容易造成误解。
mysql_alter_table
|===>innobase_check_foreign_key_index
而5.5的报错处理在执行阶段。
我们先来看看5.5的执行流程:
dict_load_foreigns
:这个函数由于承担的责任太多,只要发现错误,就笼统的抛出Error on rename of 'xxxx' to 'xxxx' (errno: xxx)
的错误.
我们来看一个外键相关的bug77467。
Alter table reply
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的做法比较好。