MySQL案例-奇怪的duplicate primary
-------------------------------------------------------------------------------------------------記錄文---------------------------------------------------------------------------------------------------------------
結論先行: 最終只是解決了這個問題, 沒有找到根本的原因, 本文只有針對這個問題的分析和思考;
現象:
在Master-5.0.X與Slave-5.7.17進行同步的時候, slave worker拋出了一個錯誤, duplicate primary;
錯誤信息如圖:
分析:
看上去是個很正常的報錯, 主鍵重復, 出現這個這個問題的可能性有不少, 不過這次的問題比較蹊蹺,
因為這個slave是用mydumper新做的, 剛開始同步幾條數據就報錯, 有點奇怪;
看了一眼表的數據, pk=13的記錄確實存在, 那么久看看relaylog, 找一下完整的語句;
找到這個語句以后, 發現事情有點不對(ノへ ̄、)
由于使用了auto_increment作為主鍵, binlog會在記錄這類語句的時候在binlog的statement之前注明主鍵的具體值;
從binlog的內容來看, 這個語句明顯不應該是插入pk=13的記錄, 應該是91391才對;
那么如果從Master把這條數據單獨導出來, 直接手動導入的話, 跳過這個錯誤, 也是能解決問題;
看了一眼relaylog, 到導出數據的時候, 都沒有再對這條數據進行修改, let's go~
PS:
因為Master的寫入很少, 所以才能這么干, 繁重業務的話, 就跳過這種辦法吧...
為了保險起見, 新建了一個測試庫, 先試一下這么導數據會不會有問題;
把數據導進去看看;
導入沒有問題, 而且數據內容也ok, 那么把數據往同步的庫里面導入試試.......
(ノへ ̄、)看樣子同步報錯并不是意外.....
后來還陸陸續續做過以下嘗試:
懷疑表有問題, 畢竟從5.0.X的庫導入到5.7.17, 所以嘗試了:
alter表; mysql_upgrade; 檢查auto_increament的值;
懷疑使用了假的relaylogㄟ( ▔, ▔ )ㄏ :
重新做同步;
語句有問題(╯‵□′)╯︵┻━┻ :
從已經有這條數據的測試庫直接用insert...select來插入數據;
全部都沒有用~
最后才把疑點放到這張表的觸發器上;
這個觸發器是用來做表字符集轉換的, 以前在別的數據庫中也用到過,這次報錯的信息也不是觸發器的內容,按道理來說應該是沒啥問題的;
不過除了觸發器, 好像真沒有什么有可能會出問題的地方了, 試著刪了這個觸發器之后, 發現一切正常了......
最后的解決方法就只能刪了所有的觸發器;
思考:
首先遇到這個問題的時候, 去查了relaylog, 第一時間的猜測是binlog的問題或者是表的問題,
因為從報錯信息里面可以看出來,
sql_thread在重演這一條語句的時候, 認為pk=13, 但是binlog里面記錄的明顯是91391;
那么就有可能是sql_thread在這一塊event的時候, 沒有認出來這個insert_id=91391的信息, 直接忽略掉了(雖然binlog都是v4, 但是天知道有什么bug不是..),
用了系統自己的auto_increament計數值(因為Master的寫入量很少, 考慮到13這個值也不大, 所以產生這種猜測);
所以檢查了表的auto_increament值, 也嘗試了mysql_upgrade和alter重建表, 但是都沒用;
之后發現binlog是statement, 這個語句并沒有把所有列的值進行顯式的賦值, 而且和后面的另外一條語句組成了一個事務,
如果把
完整的信息都列出來, 或者
把這個語句拆出來做成一個單獨的事務, 是不是就沒問題了?
所以之后單獨把那一行數據導出來, 再嘗試插入到表里面, 不管是source sql文件還是insert...select也不行;
從這幾次嘗試之后, 基本也能判斷不是SQL的問題了;
最后才把注意力放到觸發器上面, 這是測試表和業務表唯一的區別, 但是報錯里面的信息完全和觸發器沒關系;
不過在這次出問題的表上, 還是
有一些端倪顯示出觸發器可能有問題, 那就是表自己記錄的auto_increament值,
表里面的最大值是91390, 插入失敗的數據是91391, 表中記錄的auto_increament是91392;
但是發現自己對這方面的了解不多, 也沒辦法確定這個auto_increament的值是不是查找根本原因的切入點;
路漫漫..... _(:з」∠)_
PS: 源庫導出結構的時候, 已經確認源庫沒有觸發器和存儲過程, 而且也可以確認5.0.X和5.7的binlog都是v4;
PPPPPPPPPS: 畢竟從5.0.X往5.7做同步不是一個常見的場景, 姑且就當做是跨版本的同步問題吧, 如果能換成row模式的話, 好想看看會不會出問題;