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

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



仅在事务中选择MAX是安全的还是我们需要通过SELECT FOR UPDATE锁定某些内容?
无论如何有绕过交易并且仍然保持一致吗?

最佳答案

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

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


除了滚动自己的自动增量通常会导致输入错误的数字(特别是在多线程环境中)之外,您无论如何容易地计算出的内容(无论是在代码方面还是在性能方面)都不应存储。

10-06 06:17