我正在使用golang和阅读这个doc的mysql。它说
虽然在完成数据库时Close()数据库是惯用的,但sql.DB对象的设计是长期存在的。不经常打开()和关闭()数据库。
我不知道连接应该持续多久。现在,如有必要,我会打开每个http请求的连接。太频繁了吗?
答案 0 :(得分:13)
在同一份文件中进一步说明:
相反,为您需要访问的每个不同数据存储创建一个sql.DB对象,并保持该对象直到程序完成访问该数据存储。根据需要传递它,或者以某种方式在全球范围内提供它,但保持打开状态。并且不要从短期函数中打开()和关闭()。相反,将sql.DB作为参数传递给该短期函数。
如果不将sql.DB视为长期存在的对象,则可以 遇到诸如重用不良和连接共享等问题, 耗尽可用的网络资源,或者由于偶发的故障 许多TCP连接仍处于TIME_WAIT状态。这样 问题是你没有使用数据库/ sql的迹象 设计的。
打开和关闭数据库连接是一项代价高昂的操作,因此您希望尽可能避免这种情况。你肯定不希望在每次请求后关闭连接(除非每天只有几个,即使这样,只要应用程序运行,你就可以保持打开状态)
数据库/ sql包使用了connection pooling,因此您不必担心管理多个连接。
答案 1 :(得分:7)
没有权威的答案,因为它取决于您使用的驱动程序。如果你使用的是:
...那么你根本不应该关闭你的sql.DB
。这些情况下的sql.DB
代表连接池,并且在处理程序/请求/函数中使用它意味着您只是使用该池中的连接(如果可用)。
e.g。
var db *sql.DB
func setup() error {
var err error
db, err = sql.Open(...)
if err != nil {
log.Fatal(err)
}
// Other setup-related activities
}
func main()
err := setup()
if err != nil {
log.Fatal(err)
}
// No need to call `defer db.Close()` here
http.ListenAndServe(...)
}
func SomeHandler(w http.ResponseWriter, r *http.Request) {
u := User{}
res, err := db.GetThings(&u)
// No need to close this here - it's just a connection dynamically pulled
// from our sql.DB connection pool in most cases
}