我找到了解决问题的方法。
使用InnoDB
CREATE TABLE UserAccount (
UserID INT NOT NULL AUTO_INCREMENT,
Email CHAR(32) NOT NULL UNIQUE,
Password CHAR(32) NOT NULL,
Status TINYINT DEFAULT 0,
PRIMARY KEY(UserID)
);
尝试插入数据。
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com', 3341234, 0);
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com', 3341234, 0);
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com', 3341234, 0);
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test2@gmail.com', 3341234, 0);
test@gmail.com的UserID
是1和
test2gmail.com的UserID
是4,而不是2。
我希望结果为2。 解决方案是什么?
答案 0 :(得分:3)
默认innodb_autoinc_lock_mode
是" 1"。这意味着如果无法事先确定要插入的行数(例如在INSERT
查询中),InnoDB仅锁定表上的自动增量列,直到INSERT ... SELECT
语句结束。对于像查询这样的简单INSERT
,它会提前分配自动增量ID,然后立即允许对表进行其他插入,以便更快地写入。
一般来说,这意味着ID是连续的,但是如果您使用INSERT IGNORE
,这是一个简单的插入,因此ID将被分配,然后可能不会实际使用,因为该行是重复的。
如果您必须为每一行都有一个连续的标识符,则可以通过将以下行添加到my.cnf
并重新启动MySQL服务器来更改InnoDB自动增量锁定模式。
innodb_autoinc_lock_mode = 0
manual中有更多相关信息。即使在此更改之后,如果生成ID的事务被回滚或者稍后删除行,则序列中可能存在间隙,但是对于您的示例,生成的ID是" 1"和" 2"正如你所料。
如果您无法编辑my.cnf
或者回滚后存在差距,则可以编写触发器来更新主键。像下面这样的东西可以。它会为每个插件生成一个警告("列' UserID'不能为空")但它会成功插入连续的ID。不幸的是,如果您删除ID最高的用户,下一个用户将再次获得相同的ID,而如果您在序列中间删除用户,则会出现与自动增量相关的差距。
DROP TABLE UserAccount;
CREATE TABLE UserAccount (
UserID INT NOT NULL,
Email CHAR(32) NOT NULL UNIQUE,
Password CHAR(32) NOT NULL,
Status TINYINT DEFAULT 0,
PRIMARY KEY(UserID)
);
CREATE TRIGGER UserAccount_before_insert BEFORE INSERT ON UserAccount
FOR EACH ROW SET NEW.UserId = (
SELECT COALESCE(MAX(UserId), 0) + 1 FROM UserAccount);
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com', 3341234, 0);
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com', 3341234, 0);
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com', 3341234, 0);
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test2@gmail.com', 3341234, 0);
我必须添加,如果您从多个连接同时进行大量插入操作,我不完全确定此触发器的执行方式。因此,如果这是一个问题,您可能需要做更多的研究。
答案 1 :(得分:0)
在插入查询中使用IGNORE
,表示不插入重复记录。
每当您插入相同的UserID AUTO_INCREMENT
计数增加然后不同的UserID进入时,它会插入增加的auto_increment值(在您的情况下为4)
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com, 3341234, 0); -- auto_increment = 1
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com, 3341234, 0); -- auto_increment = 2
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test@gmail.com, 3341234, 0); -- auto_increment = 3
INSERT IGNORE INTO UserAccount VALUES (NULL, 'test2@gmail.com, 3341234, 0); -- auto_increment = 4