这是我上一个问题的后续(你可以跳过它,因为我在这篇文章中解释了这个问题):
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 question(见上面的链接)我发现做这样的查询更快:
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 条记录后造成死锁(实际上在这个行数上相当一致)。是否有一个原因?我不明白。谢谢你。