InnoDB 复合键上的 AUTO_INCREMENT 技巧

bod*_*odo 5 mysql innodb trigger auto-increment

与 MySQL MyISAM-Engine 相比,InnoDB-Engine 无法处理复合主键的一列声明为AUTO_INCREMENT. 例如,考虑下表:

CREATE TABLE `ExampleTable` (
     `KeyPartA` mediumint(8) unsigned NOT NULL,
     `KeyPartB` smallint(5) unsigned NOT NULL,
     `Data` text NOT NULL,
     PRIMARY KEY (`KeyPartA`,`KeyPartB`)
) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)

现在模拟AUTO_INCREMENT,我了解到,可以创建以下触发器

DELIMITER $$

CREATE TRIGGER ExampleAutoIncrement BEFORE INSERT ON ExampleTable
FOR EACH ROW BEGIN
        SET NEW.KeyPartB = (
             SELECT IFNULL(MAX(KeyPartB), 0) + 1
             FROM ExampleTable
             WHERE KeyPartA  = NEW.KeyPartA
        );
END $$

DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

现在插入工作正常,生成自动递增的值。不幸的是,我想不出一种明智的方法来获取新创建的键值。

由于LAST_INSERT_ID()没有实际的AUTO_INCREMENT列,因此它的 C 对应项都不会返回它。也不能LAST_INSERT_ID(IFNULL(MAX(KeyPartB), 0) + 1)ExampleAutoIncrement触发器内部设置值,因为 MySQL 在触发器完成后重置该值。

我想到的唯一方法是SELECT MAX(KeyPartB) FROM ExampleTable WHERE KeyPartA = ?在插入后发出 a ,这违背了触发器的全部目的。即我也可以在插入和手动增量之前执行此操作。

有没有办法从触发器或其他模拟AUTO_INCREMENT我想要的方法中获取递增的键值?

Ric*_*mes 4

我的解决方案是从 myisam 迁移到 innodb。它是这样的:

  BEGIN;
  SELECT @id := IFNULL(MAX(id),0) + 1 FROM foo WHERE other = 123 FOR UPDATE;
  INSERT INTO foo
     (other, id, ...)
     VALUES
     (123, @id, ...);
  COMMIT;
Run Code Online (Sandbox Code Playgroud)

必须进行事务以防止另一个线程获取相同的 id。