- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
SQL 文档说 LAST_INSERT_ID()
在“每个连接”的基础上工作,也就是说,最后一个插入 ID 值不会被执行的 INSERT
语句覆盖通过其他连接。
AFAIU,在 Go 中(例如与 PHP 不同)我们不会在每个客户端请求上创建单独的数据库连接。相反,我们被告知只创建一个 sql.DB
对象实例,它在后台管理一个 SQL 连接池。因此,他们说,不能保证 Go 程序中的两个连续 SQL 语句(即使在同一个线程中)将通过同一个数据库连接执行。因此,情况可能恰恰相反——两个不同的线程可以在同一个(重用的)数据库连接上执行两个不同的 SQL 语句。
问题是:sql.DB
中的这种自动连接管理会影响 sql.Result.LastInsertId()
的线程安全吗?
考虑以下情况:在一个线程中的 INSERT
语句之后,sql.DB
对象在另一个线程中重用连接,另一个线程执行另一个 INSERT
同一(重用)连接上的语句。之后,第一个线程查询 sql.Result.LastInsertId()
。
这会返回第二个 INSERT
或第一个 INSERT
的行 ID 吗?最后一个插入 ID 是在语句执行时缓存的,还是导致将单独的语句发送到 DB 连接?
最佳答案
MySQL 客户端-服务器协议(protocol)在对执行INSERT
操作的查询的响应数据包中返回LAST_INSERT_ID()
的值。通常,客户端 API 使用 SQL API 中的 sql.Result.LastInsertId()
等方法将其返回给客户端代码。不需要往返查询。
所以你的问题的答案是“第一个 INSERT”。
需要明确的是,MySQL 连接在广义上不是线程安全的。相反,它们是连续可重用的资源。多线程客户端环境通过管理串行重用使它们看起来是线程安全的。您已经在您的问题中描述了它如何适用于 golang
。
关于mysql - sql.Result.LastInsertId() 的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45520813/
我是一名优秀的程序员,十分优秀!