SQL文档说LAST_INSERT_ID()是基于“每个连接”工作的,也就是说,最后一个插入ID值不会被通过其他连接执行的INSERT语句覆盖。
AFAIU,在Go中(不像PHP ),我们不会为每个客户端请求创建单独的数据库连接。相反,我们被告知只创建一个sql.DB对象的实例,该对象在幕后管理一个SQL连接池。因此,他们说,不能保证Go程序中的两个连续SQL语句(即使在同一线程中)将通过相同的DB连接执行。因此,情况可能正好相反--两个不同的线程可以在同一个(重用的) DB连接上执行两个不同的SQL语句。
问题是:sql.DB内部的这种自动连接管理会影响sql.Result.LastInsertId()的线程安全吗
考虑以下情况:紧跟在一个线程中的INSERT语句之后,sql.DB对象重用另一个线程中的连接,而另一个线程在那个相同的(重用的)连接上执行另一个INSERT语句。然后,第一线程查询sql.Result.LastInsertId()。
这将返回第二个INSERT的行ID还是第一个INSERT的行ID?最后一个insert ID是在语句执行时缓存的,还是导致向DB连接发送一个单独的语句?
发布于 2017-08-05 19:12:46
MySQL客户端-服务器协议在响应数据包中返回LAST_INSERT_ID()的值,以响应执行INSERT操作的查询。通常,客户端API使用SQL API中的sql.Result.LastInsertId()等方法将其返回给客户端代码。不需要往返查询。
所以你的问题的答案是“第一个插入”。
需要说明的是,MySQL连接在广义上并不是线程安全的。相反,它们是可连续重用的资源。多线程客户端环境通过管理串行重用使它们看起来是线程安全的。你已经在你的问题中描述了这是如何在golang上工作的。
https://stackoverflow.com/questions/45520813
复制相似问题