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