#railsデッドロックをテキストや図で理解するのはなかなか難しかったので、最小限のアプリケーションコードで再現できないか試してみた。することで、実際に自分がデッドロックを引き起こすコードを書かないように注意できたり、同僚が書いたコードをレビューできるようになるだろう。今回は見落としがちな外部キー制約がからむデッドロックを再現してみた。再現にあたりなるべく簡潔に書けるようにRubyとActiveRecordを使い、デッドロックが起きたかどうかをテストによって検証する。以下のコードはローカルにMySQLが起動していれば動作する。endend#test_deadlock_by_foreign_keysはデッドロックを再現させるテスト、#test_avoid_deadlock_by_foreign_keysはそれを避ける実装のテスト(例外が起きないテストは何もassertする必要がない)を表している。比べてみると、子テーブルへのINSERTの前に親テーブルのレコードに排他ロックを取得しておくことで、デッドロックを回避できていることがわかる。子テーブルを持つ親テーブルにlast_tweeted_atやlast_followed_atといった更新を必要とするカラムを定義すると、デッドロックを引き起こしやすいこともわかる。今回は、外部キー制約が関わるデッドロックを再現してみたが、他のパターンについても同様の方法で再現させることでデッドロックについて理解を深めていきたい。