ギャップロック
MySQL/InnoDBのロック機構で、インデックス値の間の「ギャップ」をロックする。既存の行だけでなく、新しい行が挿入されうる範囲も対象になる。ロックした範囲への挿入を阻止することで、Repeatable Readでのファントムリードを防ぐ。
解決する問題はこうだ。ギャップロックがなければ、読み取ったばかりの範囲の途中に別のトランザクションが新しい行を挿入でき、「ファントム」が現れてRepeatable Readが崩れる。InnoDBの「ネクストキーロック」は、行ロックとギャップロックを組み合わせたもので、行とその手前のギャップの両方をロックする。たとえば SELECT ... WHERE x BETWEEN 10 AND 20 FOR UPDATE は、ギャップもロックするので、xがその範囲に入る新しい行は追加できない。トレードオフとして、ファントムは防げるが、思わぬデッドロックを起こしたり、無関係に見える挿入までブロックしたりする。InnoDBの不可解なロック競合の定番の原因だ。ギャップロックはRead Committedでは使われなくなるため、負荷によっては分離レベルを下げる理由にもなる。開発者を驚かせがちなInnoDB固有の挙動である。