sql.Result.LastInsertId() 的线程安全

use*_*418 3 mysql sql multithreading go

SQL 文档说它LAST_INSERT_ID()在“每个连接”的基础上工作,也就是说,最后一个插入 ID 值不会被INSERT通过其他连接执行的语句覆盖。

\n\n

AFAIU,在 Go 中(例如与 PHP 不同),我们不会在每个客户端请求上创建单独的数据库连接。相反,我们被告知只创建一个sql.DB对象实例,该实例在后台管理 SQL 连接池。因此,他们说,不能保证 Go 程序中的两个连续 SQL 语句(即使在同一线程中)将通过同一个数据库连接执行。因此,相反的情况可能是 \xe2\x80\x93 两个不同的线程可以在同一(重用)数据库连接上执行两个不同的 SQL 语句。

\n\n

问题是:内部的这种自动连接管理会sql.DB影响线程安全吗sql.Result.LastInsertId()

\n\n

考虑以下情况:INSERT在一个线程中的语句之后,该sql.DB对象在另一个线程中重用该连接,并且另一个线程INSERT在同一(重用)连接上执行另一条语句。之后,第一个线程查询sql.Result.LastInsertId().

\n\n

这会返回第二个INSERT或第一个的行 ID 吗INSERT?最后一个插入 ID 是否在语句执行时缓存,或者是否导致将单独的语句发送到数据库连接?

\n

O. *_*nes 5

LAST_INSERT_ID()MySQL 客户端-服务器协议将响应数据包的值返回到执行INSERT操作的查询。sql.Result.LastInsertId()通常,客户端 API 使用SQL API等方法将其返回给客户端代码。无需往返查询。

所以你的问题的答案是“第一个插入”。

需要明确的是,从广义上讲,MySQL 连接不是线程安全的。相反,它们是连续可重用的资源。多线程客户端环境通过管理串行重用使它们看起来线程安全。golang您已经在问题中描述了它的工作原理。