下面我們來複現下:
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的做法比較好。