我正在使用 MySQL 数据库。以下片段创建一条记录并从创建的记录中获取 id:
insertStmt = connection
.prepareStatement("INSERT INTO bugs (summary, status, report_date) VALUES (?, ?, ? )");
//...
insertStmt.executeUpdate();
idQuery = connection.prepareStatement("SELECT LAST_INSERT_ID()");
rs = idQuery.executeQuery();
if (rs != null) {
rs.next();
return new Long(rs.getLong(1)).toString();
}
现在,如果两个线程执行这个并且它们的执行是交错的,比如说,第一个线程插入记录,然后第二个线程插入,之后第一个线程调用 last_insert_id() 这对于这个线程来说是不正确的第二个线程已经插入了一条记录。
然而,这可以通过使用同步来克服。有没有一种方法可以在单个数据库调用中执行这两个语句?
最佳答案
LAST_INSERT_ID
按连接工作,正如您的问题所述,如果两个线程中的两个语句使用相同的连接,您可能会出现竞争条件。
您有两种解决方法:
1:每个线程使用单独的连接(不容易,但这确实是缩放和感知的最佳选择;使用连接池)
2:使用executeUpdate
的形式即records the auto-generated key在同一个 API 调用中,允许您稍后使用 getGeneratedKeys
读取它,这样您就不必在第二个查询中使用 LAST_INSERT_ID
,从而避免竞争条件。有一个类似的形式 prepareStatement
可以在准备好的语句中使用。
选项 2 可能是您短期内想要的。选项 2 中的链接直接指向该 API。 This link是一篇概述如何使用它的 MySQL 文章。
关于java - JDBC一次执行多个语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20640732/