后跟 SELECT LAST_INSERT_ID 时 INSERT 不起作用

Posted

技术标签:

【中文标题】后跟 SELECT LAST_INSERT_ID 时 INSERT 不起作用【英文标题】:INSERT doesn't work when followed by SELECT LAST_INSERT_ID 【发布时间】:2019-03-07 22:26:53 【问题描述】:

有很多关于LAST_INSERT_ID()的问题

就我而言,问题是:

INSERT 后跟SELECT LAST_INSERT_ID() 时,没有记录被插入

INSERT INTO sequences (state)  VALUES (0);
select LAST_INSERT_ID();
>>> 80  // nothing is added to DB

INSERT自己的作品OK

INSERT INTO sequences (state)  VALUES (0);
>>>
select LAST_INSERT_ID();
>>> 81 // row is inserted

为了测试我使用的是 SequelPro,DB 是 Amazon 的 RDS mysql。当我使用 Python 的 MySQLdb 模块时,也会出现同样的问题。

理想情况下,我想插入行,取回它的 ID 以供将来识别和使用。

【问题讨论】:

【参考方案1】:

您应该一次运行一个查询。大多数 SQL 接口不允许多个查询。

MySQL 允许单个查询被; 终止,但如果; 后面有任何单词(注释除外),则为语法错误,这将导致整个请求失败。所以 INSERT 也不会运行。

MySQL 确实有一个允许多查询的连接选项,但默认情况下它是不活动的。见https://dev.mysql.com/doc/refman/8.0/en/c-api-multiple-queries.html

确实没有理由使用多查询。只需在INSERT 之后将SELECT LAST_INSERT_ID() 作为单独的查询运行即可。只要你使用相同的连接,它就会给你正确的答案。

【讨论】:

这会造成竞争条件吗?我正在并行运行 400 多个节点,如果一个节点 INSERT 在另一个节点之后会怎样 @aaaaaa 为什么你还在怀疑? LAST_INSERT_ID() 是线程安全的,它基于连接。manual 表示“这种行为确保每个客户端都可以检索自己的 ID,而不用担心其他客户端的活动,也不需要锁或事务。”它当所有节点使用相同的连接或分开的连接并且不要忘记无竞争条件时会没问题 是的,LAST_INSERT_ID() 的范围仅限于您自己的会话。如果不是,它对任何人都没有多大用处!此外,如果它不是线程安全的,那么将它与 INSERT 放在一个多查询中将无济于事。它仍然受制于竞争条件。

以上是关于后跟 SELECT LAST_INSERT_ID 时 INSERT 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

MySQL LAST_INSERT_ID() 与 INSERT INTO tablea SELECT FROM tableb

select last_insert_id()使用注意事项

SELECT LAST_INSERT_ID() *更新

使用 select last_insert_id 生成唯一 ID

阿里读写分离数据源SELECT LAST_INSERT_ID()获取不到id

在Spring中用select last_insert_id()时遇到问题