Mysql 获取触发器中生成的用于进一步请求的id

Mysql 获取触发器中生成的用于进一步请求的id,mysql,node.js,innodb,Mysql,Node.js,Innodb,我有一个包含两列的表: caseId,引用外部表列 caseEventId,int,对于给定的caseId是唯一的,我想为相同的caseId自动递增 我知道基于另一列的自动增量选项在mySql和InnoDb中不可用: 所以我将caseEventId生成一个触发器。我的桌子: CREATE TABLE IF NOT EXISTS mydb.caseEvent ( `caseId` CHAR(20) NOT NULL, `caseEventId` INT NOT NULL DEFAU

我有一个包含两列的表:

  • caseId,引用外部表列
  • caseEventId,int,对于给定的caseId是唯一的,我想为相同的caseId自动递增
我知道基于另一列的自动增量选项在mySqlInnoDb中不可用:

所以我将caseEventId生成一个触发器。我的桌子:

CREATE TABLE IF NOT EXISTS mydb.caseEvent (
  `caseId` CHAR(20) NOT NULL,
  `caseEventId` INT NOT NULL DEFAULT 0,
  PRIMARY KEY (`caseId`, `caseEventId`),
  # Foreign key definition, not important here.
ENGINE = InnoDB;
还有我的扳机:

CREATE DEFINER=`root`@`%` TRIGGER `mydb`.`caseEvent_BEFORE_INSERT` BEFORE INSERT ON `caseEvent` FOR EACH ROW
BEGIN
    SELECT COALESCE((SELECT MAX(caseEventId) + 1 FROM caseEvent WHERE caseId = NEW.caseId),0)
        INTO @newCaseEventId;
    SET NEW.`caseEventId` = @newCaseEventId;
END
有了这个,我得到了caseEventId,它会自动递增

但是,我需要在INSERT事务中的进一步调用中重新使用此新caseEventId,因此我将此id放入触发器中的@newCaseEventId中,并在以下说明中使用它:

START TRANSACTION;
INSERT INTO mydb.caseEvent (caseId) VALUES ('fziNw6muQ20VGYwYPW1b');
SELECT @newCaseEventId;
# Do stuff based on @newCaseEventId
COMMIT;
这似乎很好,但。。。那么并发性、使用连接池等呢

这个@newCaseEventId变量是否将与使用相同连接的所有客户端共享,当客户端服务器启动两个并发事务时,我是否会遇到问题?这是在nodejs下使用mysql

这安全吗,还是有更安全的方法?谢谢


编辑2020/09/24

仅供参考,我完全放弃了这种方法。我试图以一种不应该使用的方式使用db

基本上,我已经删除了caseEventId,以及任何应该基于给定列值很好地递增的索引


取而代之的是,当我检索数据时,我依靠读端正确编写的查询来重新创建caseEventId字段…

这没有问题,每个客户端都有一个用户定义的变量

这意味着每个用户都有自己的使用定义变量

用户定义的变量是特定于会话的。一个客户端定义的用户变量不能被其他客户端看到或使用。(例外情况:有权访问性能模式用户_variables_by_thread表的用户可以查看所有会话的所有用户变量。)给定客户端会话的所有变量在该客户端退出时自动释放。


这没有问题,用户定义的变量是每个客户端的一个变量

这意味着每个用户都有自己的使用定义变量

用户定义的变量是特定于会话的。一个客户端定义的用户变量不能被其他客户端看到或使用。(例外情况:有权访问性能模式用户_variables_by_thread表的用户可以查看所有会话的所有用户变量。)给定客户端会话的所有变量在该客户端退出时自动释放。


通过这样做,您可以创建一个竞赛条件。换句话说,如果两个并发会话同时插入会怎么样?对于
max(caseEventId)+1,它们都将读取相同的值。最终,除了锁定表之外,您无法实现每个
caseId
的自动增量。@Bill Karwin这部分是我担心的。如果您有关于如何在不造成潜在死锁的情况下实现表锁的指南,我很感兴趣!我会的。大多数人都避免这样做,因为如果你的应用程序需要在表上同时执行高速率的查询,它会严重限制吞吐量。但是如果你的查询率很低,它也可以工作。另一个更常见的解决方案是忘记对你的caseEvent按caseId独立编号。只需使用一个自动增量。这样做可以创建一个竞争条件。换句话说,如果两个并发会话同时插入会怎么样?对于
max(caseEventId)+1,它们都将读取相同的值。最终,除了锁定表之外,您无法实现每个
caseId
的自动增量。@Bill Karwin这部分是我担心的。如果您有关于如何在不造成潜在死锁的情况下实现表锁的指南,我很感兴趣!我会的。大多数人都避免这样做,因为如果你的应用程序需要在表上同时执行高速率的查询,它会严重限制吞吐量。但是如果你的查询率很低,它也可以工作。另一个更常见的解决方案是忘记对你的caseEvent按caseId独立编号。只需使用自动增量。我的客户端是nodejs/express服务器。它将并行处理多个请求,并启动并发mySql查询。这些查询来自同一台服务器,它们是否会被视为来自同一台客户机?我仍然不清楚如何处理连接。你必须在某个地方有一个连接,然后关闭该连接(我希望如此),或者有一个连接,然后通过该连接发送所有请求?是的,我为每个交易打开和关闭连接,所以根据你的反应,我想我没事。剩下的是比尔·卡温的话,以及为了避免比赛条件而锁定积分榜的必要性。谢谢是的,锁上桌子是一种可能,而使用colun UNIQUE则是另一种可能。有一个很好的理由,为什么自动增量在mysql中显示出来并且可以工作,在你的应用程序操作系统硬词中做这些,如果你只需要不必要的数字。我的客户端是一个nodejs/express服务器。它将并行处理多个请求,并启动并发mySql查询。这些查询来自同一台服务器,它们是否会被视为来自同一台客户机?我仍然不清楚如何处理连接。你必须在某个地方有一个连接,然后关闭该连接(我希望如此),或者有一个连接,然后通过该连接发送所有请求?是的,我为每个交易打开和关闭连接,所以根据你的反应,我想我没事。剩下的是比尔·卡温的话,以及为了避免比赛条件而锁定积分榜的必要性。谢谢是的,锁上桌子是一种可能,而使用colun UNIQUE则是另一种可能。有一个很好的理由,为什么自动增量在mysql中被强调并起作用,如果你只需要不必要的数字,那么在你的应用程序操作系统硬词中就可以做到这一点。