我有这个结构的桌子:

CREATE TABLE IF NOT EXISTS `message` (
  `id` bigint(20) NOT NULL,
  `appKey` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
  `text` text COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

和主键(idappKey
我希望每个appKey都有独立的id自动递增。所以我用扳机。
CREATE TRIGGER `messageId` BEFORE INSERT ON `message`
 FOR EACH ROW begin
    declare v_messageId bigint(20) unsigned default 0;
    SELECT max(id) INTO v_messageId FROM message WHERE appKey = new.appKey;
    if (v_messageId IS NULL) THEN
        set v_messageId=0;
    end if;
    SET new.id=v_messageId + 1;
end

在我试图同时插入两个数据库连接(我在应用程序中使用连接池)中的两行之前,它工作正常。插入第一行。但第二次抛出错误ER_DUP_ENTRY:键“PRIMARY”的重复项“18 secretkey”。
我知道为什么会这样。我的问题是:MySQL是否可以完成这个任务,或者我必须使用不同的数据库(可能是PostgreSQL因为顾问锁的缘故)?
编辑:
在表中,我有以下行:
id | appKey |文本
---+--------+-----------
1 |键1 |某事
2 |键1 |某事
1 |键2 |某事
2 |键2 |某事
3 |键1 |某事
错误是在我尝试插入这两行之后:
appKey |文本
-------+-------
键1 |某物
键1 |某物

最佳答案

我个人强烈建议你不要自己管理身份证。这样做没有商业价值。
如果你想坚持下去,出于某种原因,至少要利用LAST_INSERT_ID(expr)。这是MySQL中生成序列的唯一多用户安全方法。此外,还需要额外的表来存储每个appKey的序列。

CREATE TABLE message_seq (
  appKey VARCHAR(64) NOT NULL PRIMARY KEY,
  seq BIGINT(20) NOT NULL
);

你的扳机会像
DELIMITER //
CREATE TRIGGER `messageId`
BEFORE INSERT ON `message`
FOR EACH ROW
BEGIN
  INSERT INTO message_seq(appkey, seq) VALUES (NEW.appKey, LAST_INSERT_ID(1))
  ON DUPLICATE KEY UPDATE seq = LAST_INSERT_ID(seq + 1);
  SET NEW.id = LAST_INSERT_ID();
END//
DELIMITER ;

这是一个SQLFiddle演示
进一步阅读:
LAST_INSERT_ID()

10-08 19:22