【问题标题】:AUTO_INCREMENT and LAST_INSERT_IDAUTO_INCREMENT 和 LAST_INSERT_ID
【发布时间】:2013-01-27 11:28:21
【问题描述】:

我正在使用 AUTO_INCREMENT,我想获取插入行的 ID,以便我可以使用 ID 作为两个表之间的公共字段来更新另一个表。

我知道LAST_INSERT_ID 将得到最后一个ID。但是,我担心的是,许多用户同时访问数据库。因此,可能有另一个进程访问了该表并同时插入了一个新行。

LAST_INSERT_ID 是否只返回最后一个 ID 而不管使用的是 connection,还是只返回我正在使用的 connection 的最后一个 ID?

注意,我正在使用 Tomcat 服务器中的连接池访问 MySQL 数据库。

总而言之,我需要在表 A 中插入一个自动递增的行,而不是在表 B 中插入一行,这需要使用 AUTO_INCREMENT 值链接到表 A。

【问题讨论】:

  • 请提供更多详细信息,以便回答。但您仍然可以使用 KeyHolder。

标签: mysql


【解决方案1】:

LAST_INSERT_ID 返回当前会话的最后一个插入 ID。 只要您在当前连接中插入的条目不超过一个,它就有效。

更多信息在这里:https://dba.stackexchange.com/questions/21181/is-mysqls-last-insert-id-function-guaranteed-to-be-correct

(我会链接到 mysql.com,但它目前对我来说已关闭)

【讨论】:

  • LAST_INSERT_ID 是全球电话吗?特定表没有LAST_INSERT_ID 吗?
  • @user961627 人们应该始终知道,在当前会话中插入的最后一张表。
【解决方案2】:

LAST_INSERT_ID()上下文中工作,它应该在事务中或在用户定义的存储过程或用户定义的函数中。

【讨论】:

  • 谢谢 ... 在 Java 中,如果我使用 set auto commit 为 false 并提交更改,它应该可以完成这项工作吗?
【解决方案3】:
SELECT max(employeeid) FROM Employee;

上面的查询返回 Employee 表中最后插入记录的employeeid 的值,因为employeeid 是一个自增列。这似乎没问题,但是假设两个线程同时执行插入操作,你可能会得到最后插入记录的错误ID!

别担心,MySQL 提供了一个函数,它返回最后插入记录的自增列的值。

SELECT LAST_INSERT_ID();

LAST_INSERT_ID() 始终是特定于连接的,这意味着即使从不同的连接同时执行插入操作,它总是返回当前连接特定操作的值。

所以你必须先在 Employee 表中插入记录,运行上面的查询来获取 id 值并用它来插入到第二个表中。

【讨论】:

  • 谢谢 .. 我是否需要使用事务 - setAutocommit(false) - 才能使 LAST_INSERT_ID 工作。或者只要我使用相同的连接,它应该可以正常工作。
  • @user836026 为了安全起见,无论是否在事务中,您都可以在 INSERT 之后调用此 SET,然后再次提及事务与更可能的 MAX 情况更相关如果在事务中调用会产生所需的结果,但是,LAST_INSERT_ID 是首选!
【解决方案4】:

LAST_INSERT_ID 是特定于连接的。确实如此,但如果使用连接池,则应小心。当您在循环中执行连续的INSERT IGNORE 语句并且池在每次迭代时为您提供相同的连接时,这可能会出现问题。

例如;假设您收到以下各项的相同(打开)连接:

INSERT IGNORE ... some-new-id >>> LAST_INSERT_ID 返回100

INSERT IGNORE ... some-existing-id >>> LAST_INSERT_ID 仍然返回100(之前操作的结果)

在调用LAST_INSERT_ID之前检查INSERT操作是否实际上插入了任何行总是好的。

【讨论】:

  • 你提到last_insert_id的连接池有问题,如何模拟这种情况?我尝试用spring、mybatis和c3p0连接池测试这个案例,将maxPoolSizeminPoolSize都设置为1,在线程的帮助下循环插入多条记录。但是我发现在这种情况下没有问题,last_insert_id 可以得到正确的结果。我的测试哪里错了或者我错过了什么?
  • 如果您插入的所有记录都是新的,则没有问题。但是如果您的插入被忽略并且您调用last_insert_id,则返回的结果可能不属于最近的插入尝试。这可能是其他一些线程在同一连接上插入了一些行的结果。为了安全起见,请检查插入结果并在必要时致电last_insert_id
  • 感谢您的回复。如果INSERT IGNORE 不插入记录,则last_insert_id 将返回0 或最后插入id。这不是我们预期的正确结果。所以last_insert_id总是有问题insert ignore不管有没有连接池都没有真正的插入,对吧?
  • 是的,你是对的。但一个不同之处在于,使用连接池时,即使在第一次 INSERT IGNORE 操作时也必须小心。
猜你喜欢
  • 2020-10-25
  • 2012-10-19
  • 1970-01-01
  • 2014-02-06
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 2012-01-16
  • 2011-04-19
相关资源
最近更新 更多