書いたものをクロス投稿しました。5.7と8.0でロック状態を確認する(sys.innodb_lock_waitsビュー)に書いた、performance_schema.data_locksテーブルperformance_schema.data_lock_waitsテーブルを見ながら、「再現1」の動きを確かめてみます。※残念ながら(?)sys.innodb_lock_waitsビューはあまり役に立ちませんでした。「他を待たせていないロック」を表示しないと意味がないので...。ロックの種類について、軽く説明を書きました。テーブルと初期データを登録しますが、それと同時に、実験の流れが分かりやすいようにデッドロックを検出しない(タイムアウトまで待つ)innodb_deadlock_detect=0の設定にしておきます。つのテーブルでロックの状況を見てみましょう。行目:同・id=25の行に対する排他ロックが表示されました。実在するレコードのうち、id=23のすぐ上の行はロック対象という動作を示しています(ので、id=15の行はロック対象外です)。ロックで待たせているものはないのでperformance_schema.data_lock_waitsは空です。COMMITTED相当になります。UPDATE;ロック待ち状態になりました。行目:同・id=25の行に対する排他ロックが表示されました。performance_schema.data_lock_waitsには、トランザクション2のid=20の行に対する排他ロックがトランザクション1の同じ行に対する排他ロックに待たされていることを示す行が表示されました。※id=20の行のロックで待たされているので、トランザクション2はまだid=25の行ロックを取りに行く前の状態です。ここで、トランザクション1でid=18の行をINSERTしてみます。75);デッドロックで待ち状態になりました(最初の設定により、タイムアウトするまでエラーは出ないようになっています)。行目にINSERTによるid=20に対する排他・ギャップ・挿入インテンションロックが増えました(id=18のすぐ上に実在する行に対するロック)。行目に、「id=20の行に対して、トランザクション1がトランザクション2に待たされている」ことを示す情報が増えました。デッドロックの完成です!ここで、タイムアウトまで待ってから、ロックの状況を見てみます。行目は実際に挿入したid=18の行への排他・ギャップロックになっています。※まだCOMMITしていない状態です。行に対してお互いに逆順でロックを取ろうとしなくてもデッドロックは成立するということになります。考えると、最後にトランザクション1でINSERTする行が、id=14:INSERTでロックを取るのがid=15の行になるのでデッドロックしないid=16・17・19:id=18と同様ロックを取るのがid=20の行になるのでデッドロックするid=21:ロックを取るのがid=25の行になるのでデッドロックしない(トランザクション2はid=25のロックを取ろうとする前で止まっているため)となります。※インデックスが降順の場合はもしかすると上下関係が逆かもしれません(未確認)。いうわけで、UPDATE・DELETEでどうなるのかについては、皆さんで試してみてください。さん、良いネタの提供ありがとうございました。Qrunch.netサーバー提供フィードバックを送信する。