web-dev-qa-db-ja.com

削除して挿入すると、キーPRIMARYの重複エントリがスローされる

複合PKがあり、そのPK値の1つを更新する必要があります。しかし、内部の問題のため、PK列に対して更新クエリを実行できません。

したがって、私は[〜#〜] delete [〜#〜]および[〜#〜] insert [〜#〜]クエリを実行しています。

このDELETEINSERTTRANSACTION(READ COMMITTED)の内部で行われます。

ただし、2つのリクエストが同じ行を更新する場合もあります。キーPRIMARYの重複エントリでエラーがスローされます。これはランダムに発生します。この問題をローカルで再現するために何度も試みましたが、根本的な原因を見つけることができませんでした。

注:内部の制限により、次のことを試すことができませんでした。

  1. クエリをPKに更新
  2. クエリを置き換える
  3. 重複して挿入または無視クエリを挿入
  4. 現在このテーブルに実行中のIDを追加すると、大規模な移行になります。

この問題について親切に私を助けてください。

更新:

テーブル構造の例:

       Table: temp
Create Table: CREATE TABLE `temp` (
  `id1` int(11) NOT NULL,
  `id2` int(11) NOT NULL,
  `id3` int(11) NOT NULL,
  `value` int(11) DEFAULT NULL,
  PRIMARY KEY (`id1`,`id2`,`id3`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

サンプルデータ:

+-----+-----+-----+-------+
| id1 | id2 | id3 | value |
+-----+-----+-----+-------+
|   1 | 100 | 111 |   123 |
|   2 | 200 | 222 |   456 |
+-----+-----+-----+-------+

サンプルクエリ:

トランザクションT1はto update ID1=3 value where id2=100を試行します

Delete from temp where id2=100
Insert into temp values(3,100,111,123);

トランザクションT2はto update ID1=3 value where id2=100を試行します

Delete from temp where id2=100
Insert into temp values(3,100,111,123);

削除と挿入の数は常に同じです

5
vinieth

@vinieth

id1id2およびid3は主キーであるため、値を複製することはできません。正しい?

id1を更新するだけの場合は、UPDATEおよびDELETEステートメントの代わりにINSERTステートメントを使用することをお勧めします。削除と挿入を行うことでリソースを消費し、それも悪い習慣だからです。

あなたは単にステートメントを次のように書くことができます

UPDATE `temp`
SET
   id1=3
WHERE
   id2=100;

の代わりに

Delete from temp where id2=100;
Insert into temp values(3,100,111,123);

両方のステートメントの違いを確認できます。

また、DBでの一括操作に関しては、直面しているエラーについて話しても問題はありません。

DBエンジンはよりインテリジェントです。両方のステートメントを同時に実行する場合。 DBは、実行前にステートメントのリストを準備します。したがって、ステートメントを準備する時点で、それはスタックメモリ内にとどまります。そして、クエリの準備後、実行時間を計算し、優先順位に並べ替えます。その場合、挿入操作が最優先されます。そのため、DBは挿入操作を実行しようとして値を検出し、「PRIMARY KEYの重複エントリ」エラーをスローします。

解決策:DELETE and INSERTの代わりにUPDATEステートメントを使用したくない場合。 id1から主キーを削除し、結果を確認してください。ただし、UPDATEステートメントを使用することをお勧めします。

編集:

このエラーの原因となる別のシナリオもあります。両方のクエリを同時に実行しようとした場合。どちらも並行して実行できます。また、DELETEINSERTの両方が同時に実行されたため、INSERT操作で、まだ削除されていない値が見つかりました。そして、エンジンはこのエラーを返します。

1
Mayur