発生している問題は、MySQLが挿入しようとしている値のテーブル行をロックするだけでなく、前のid
の間のすべての可能な値をロックするために発生します。 次のIDを順番に並べて、次の例を再利用します。
DROP TABLE IF EXISTS foo;
CREATE TABLE `foo` (
`i` INT(11) NOT NULL,
`j` INT(11) DEFAULT NULL,
PRIMARY KEY (`i`),
UNIQUE KEY `jk` (`j`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
INSERT INTO foo VALUES (5,5), (8,8), (11,11);
トランザクションTX1:
から開始するとします。START TRANSACTION;
REPLACE INTO foo VALUES(8,8);
次に、トランザクションを開始した場合TX2
、INSERT
が何であれ またはREPLACE
id
を使用する 5〜11がロックされます:
START TRANSACTION;
REPLACE INTO foo VALUES(11,11);
MySQLは、ここで説明する「ファントムの問題」を回避するためにこの種のロックを使用しているようです: http://dev.mysql.com/doc/refman/5.0/en/innodb-next-key-locking.html 、MySQLは、インデックス行ロックとギャップロックを組み合わせた「次のキーロック」を使用します。これは、前のIDと次のIDの間で多くの可能なIDをロックし、前のIDと次のIDもロックすることを意味します。 。
これを回避するには、異なるトランザクションに挿入されたレコードが重複しないように、または少なくともすべてのトランザクションを同時に実行しないようにレコードを挿入するサーバーアルゴリズムを作成して、TX
を作成してください。 お互いを待つ必要はありません。