これは私の以前の質問のフォローアップです (この投稿で問題を説明しているのでスキップできます):
MySQL InnoDB SELECT...LIMIT 1 FOR UPDATE Vs UPDATE ... LIMIT 1
環境:
- Glassfish 上の JSF 2.1
- JPA 2.0 EclipseLink および JTA
- MySQL 5.5 InnoDB エンジン
私はテーブルを持っています:
CREATE TABLE v_ext (
v_id INT NOT NULL AUTO_INCREMENT,
product_id INT NOT NULL,
code VARCHAR(20),
username VARCHAR(30),
PRIMARY KEY (v_id)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
次のような 20,000 件のレコードが入力されます (product_id
すべてのレコードで 54 件、code
ランダムに生成され、一意であり、ユーザー名が NULL に設定されています)。
v_id product_id code username
-----------------------------------------------------
1 54 '20 alphanumerical' NULL
...
20,000 54 '20 alphanumerical' NULL
ユーザーが製品 54 を購入すると、そのテーブルからコードを取得します。ユーザーが複数回購入すると、毎回コードを取得します (ユーザー名に一意の制約はありません)。私は高活動の準備をしているので、次のことを確認したいと思います。
- 同時実行/デッドロックが発生しない
- パフォーマンスは、必要となるロック メカニズムの影響を受けません。
SO の質問 (上記のリンクを参照) から、このようなクエリを実行する方が高速であることがわかりました。
START TRANSACTION;
SELECT v_id FROM v_ext WHERE username IS NULL LIMIT 1 FOR UPDATE;
// Use result for next query
UPDATE v_ext SET username=xxx WHERE v_id=...;
COMMIT;
username
ただし、列にインデックスを使用する場合にのみ、デッドロックの問題が見つかりました。インデックスを追加すると少し高速化できると思いましたが、約 19,970 レコードの後でデッドロックが発生します (実際には、この行数ではかなり一貫しています)。これには理由がありますか?理解できない。ありがとうございました。