はid
をプライマリキーとし、state
(CHAR(1))は "x"または "y"となり、state_position
(INT)です。これらの列には索引はありません。ストレージエンジンは無駄です。MySQL - ロックを取得しようとするとデッドロックが見つかりました
state_positionsは常に連続している必要があり、私は「X」の状態で5人のユーザーがいる場合は、特定の状態、すなわちのための重複位置は存在しないかもしれない、彼らのstate_positionsでなければなりません1,2,3,4,5
これは、デッドロックが発生し、私が実行しているクエリです:テスト用
insert into `tt_users` (`state`, `state_position`)
values ('x',
(SELECT MAX(state_position) AS maxStatePosition
FROM tt_users AS u2
WHERE u2.state='x') + 1
)
、私は同時に、ユーザーを大量に挿入され、毎回私は、デッドロックエラーを得ました。
私はこの質問への答え - Working around MySQL error "Deadlock found when trying to get lock; try restarting transaction" - デッドロックは何が起こることができると言うので、デッドロックを防ぐために私のクエリで何をすべきか理解できませんでした。
私は仕事にこれを取得し、一貫して動作するために管理する唯一の方法は、この(言語はPHPです)です:
PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
はその後、手動でテーブルをロックし、私のクエリを実行:
SET autocommit=0;
LOCK TABLES
tt_users WRITE,
tt_users AS u2 WRITE;
insert into `tt_users` (`state`, `state_position`)
values ('x',
(SELECT MAX(state_position) AS maxStatePosition
FROM tt_users AS u2
WHERE u2.state='x') + 1
);
COMMIT;
UNLOCK TABLES;
その後、
そして:私は4回同時にコードを実行されたこと方法で
PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
、各インスタンスinser 2500人のユーザーが問題なく使用できます。
これを有効にする唯一の方法ですか、または手動でテーブルをロックしなくてもデッドロックを100%確実に防ぐことができますか?
UPDATE:@のwallykの答えパー
、私は次のことを試してみました:
1)トランザクションでクエリを置く - まだエラー
2デッドロック)WITH CONSISTENT SNAPSHOT
との取引を開始し、READ WRITE
、 READ ONLY
。 3つのオプションすべてにPDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
を設定する必要があります。 WITH CONSISTENT SNAPSHOT
とREAD WRITE
はまだ私にデッドロックエラーを与えましたが、READ ONLY
は当然INSERT
の実行を許可しませんでした。
今のところ、手動でテーブルをロックしているように見えるのは、動作する唯一のものです。
ありがとう、私はこれらのすべてを試し、結果を得る。 – GTCrais
あなたの提案を試した結果の質問を更新しました。残念ながら、それはうまくいきませんでした。 – GTCrais