在InnoDB中使用MAX模拟自动增量的最快,最安全的方法

时间:2019-01-24 07:22:36

标签: mysql sql transactions

假设我们有一个具有以下架构的表:

CREATE TABLE Persons (
sid int NOT NULL AUTO_INCREMENT,
groupName varchar(255) NOT NULL,
userIdInGroup int,
PRIMARY KEY (sid));

我们要基于该组的最后一个userId为同一组中的每个新用户分配一个自动递增的userId,即我们要在每个组中模拟一个自动递增的userId。

由于要考虑MAX(userIdInGroup)插入新的userId,因此需要包装选择并插入事务中。像这样:

START TRANSACTION
SET @a = (SELECT MAX(userIdInGroup) FROM Persons WHERE groupName= 'Foo') +1;
INSERT THE NEW ROW USING userIdInGroup = @a
COMMIT 
  1. 在交易中选择MAX是安全的还是我们需要通过SELECT FOR UPDATE锁定某些内容?
  2. 反正还有绕过交易并且仍然保持一致吗?

1 个答案:

答案 0 :(得分:1)

我不是MySql的人,但是我对其他数据库确实有足够的经验,知道这是一个非常糟糕的主意。可以使用UserIdInGroup轻松计算出row_number

SELECT sid, 
       groupName, 
       ROW_NUMBER() OVER(PARTITION BY groupName ORDER BY sid) AS userIdInGroup
FROM Persons

除了滚动自己的自动增量通常会导致输入错误的数字(尤其是在多线程环境中)外,您不应轻易存储(在代码和性能方面)容易计算的结果无论如何。