问题描述
假设我们有一个具有以下架构的表:
Assume that we have a table with the following schema:
CREATE TABLE Persons (
sid int NOT NULL AUTO_INCREMENT,
groupName varchar(255) NOT NULL,
userIdInGroup int,
PRIMARY KEY (sid));
我们希望根据组的最后一个 userId 为同一组中的每个新用户分配一个自动递增的 userId,即我们希望在每个组内模拟一个自动递增的 userId.
We want to assign each new user in the same group an auto-increment userId based on the last userId of the group, i.e. we want to emulate an auto-increment userId within each group.
由于我们考虑 MAX(userIdInGroup) 插入新的 userId,因此我们需要将 select 和 insert 包装到事务中.像这样:
Since we are inserting the new userId considering the MAX(userIdInGroup) we need to wrap select and insert in a transaction. Something like this:
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
轻松计算:
I'm not a MySql person, but I do have enough experience with other databases to know that this is a really bad idea. This UserIdInGroup
can easily be calculated using row_number
:
SELECT sid,
groupName,
ROW_NUMBER() OVER(PARTITION BY groupName ORDER BY sid) AS userIdInGroup
FROM Persons
除了滚动您自己的自动增量通常最终会给出错误的数字(尤其是在多线程环境中)之外,您可以轻松计算的内容(在代码和性能方面)不应存储无论如何.
And besides the fact that rolling your own auto-increment usually ends up giving wrong numbers (especially in a multi-threaded environment), what you can calculate easily (both in the code and in the performance aspect) should not be stored anyway.
这篇关于在 InnoDB 中使用 MAX 模拟自动增量的最快和最安全的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!