MySQLのslaveでDuplicate entryエラーが出た時の対処

こんにちは。小宮です。
このまえ出たエラーの記録です。

・エラーログ
[shell]>show slave status\G

Last_Error: Error ‘Duplicate entry ‘1133523-2013-08-18 05:03:01’ for key ‘PRIMARY” on query. Default database: ‘*****’. Query: ‘INSERT INTO event_****_logs …[/shell]

時刻がプライマリキーになってるから重複してる感じのエラーなような。
ログとかセッションとか重複しやすい感じがします。

念のためmysqldumpのオプションをみたものの、
–skip-optは入ってないのでoptが勝手について–add-drop-tableは有効なはず。

[shell]MYDUMP_PAR=’–single-transaction –dump-slave=2 –routines –include-master-host-port –all-databases'[/shell]
http://dev.mysql.com/doc/refman/5.5/en/mysqldump.html

データ投入後にreset slaveしてログファイルとポジション合わせてstart slaveするなど手順には問題がないように見えました。

お客さまに重複エントリは全部skipしていいか確認いただいたところ
Insertでプライマリキーが被ってるのは大丈夫なのかは別途開発側で確認でとりあえずskipという話に。
(対象がサービスで使用していないいので復旧優先ということだったと思います。不整合が気になるならマスタからdump撮り直すのが良いです。)

・エラーのクエリをskipする方法
1つだけなら、
[shell] SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;[/shell]
ですがいっぱいでてくる場合は
Last_SQL_Errno: 1062
こちらのエラー番号を指定してスキップ。重複エントリを全部スキップするということです。

maatkit(後継はperconatoolkit)が入ってるなら
[shell]mk-slave-restart -u root -pcat /root/.mysql_pwd –error-numbers 1062 –verbose[/shell]
標準出力に出るのでリダイレクトしとくと後でスキップしたクエリを確認できます。(perconatoolkitだとmkのところがptになります)

入ってないなら、
他に以下のようにmy.cnfに書く手もある。(要mysqld再起動)
[shell]slave-skip-errors=1062[/shell]

後継版だと、pt-slave-restartみたいですね。
http://fr.slideshare.net/billkarwin/percona-toolkit
http://jitsu102.hatenablog.com/entry/2012/03/08/073448

別案件でもログやセッション等のデータが重複することは前にありました。
もしdump撮り直すなら、更新がかからないようにロックしてから数秒待てポジション確認してから撮るのがいいかもしれません。
全てInnoDBで–single-transaction使ってても重複でることはあるようです。

と思ったらこの事件の顛末が判明しましたのでそれも記録しておきます。
実は、バイナリログファイルとポジションをdumpデータの中身見るのでなく、
ロックした後に手でshow master status;してからdump撮ってたから、
微妙に更新されてた11クエリ分くらいdumpデータのが新しかったから重複した!ということでした。
head -30 dumpdata とか、zcat dumpdata.gz|head -30とかで確認しないとダメみたいですね。
–masta-dataつけてdumpとってるならちゃんと見ようというお話でした。
※–masta-dataをつけるとCHANGE MASTER文がdumpデータの最初のほうに記録されます。
 1だと実行されて、2だとコメントになります。データ移設の時に古いマスタ向くの防止する意味で2にしてたのでした。

以上、見ていただいてありがとうございました。

おすすめ記事