我有一个使用net / http的应用。我注册了一些http的处理程序,需要从数据库中获取一些东西才能继续编写响应并完成请求。
我的问题是关于连接到这个数据库的最佳实践。我希望每分钟一次请求或每秒10次请求。
每次请求进入时,我都可以连接到每个处理程序中的数据库。(这会为每个请求产生一个到mysql的连接?)
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"net/http"
"fmt"
)
func main() {
http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) {
db, err := sql.Open("mysql","dsn....")
if err != nil {
panic(err)
}
defer db.Close()
row := db.QueryRow("select...")
// scan row
fmt.Fprintf(w,"text from database")
})
http.ListenAndServe(":8080",nil)
}
我可以在app start连接到数据库。每当我需要使用数据库时,我就Ping它,如果它关闭了,我就重新连接它。如果它没有关闭,我继续使用它。
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"net/http"
"fmt"
"sync"
)
var db *sql.DB
var mutex sync.RWMutex
func GetDb() *sql.DB {
mutex.Lock()
defer mutex.Unlock()
err := db.Ping()
if err != nil {
db, err = sql.Open("mysql","dsn...")
if err != nil {
panic(err)
}
}
return db
}
func main() {
var err error
db, err = sql.Open("mysql","dsn....")
if err != nil {
panic(err)
}
http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) {
row := GetDb().QueryRow("select...")
// scan row
fmt.Fprintf(w,"text from database")
})
http.ListenAndServe(":8080",nil)
}
哪种方式最好,还是有其他方法更好。让多个请求使用相同的数据库连接是一个坏主意吗?
我很不情愿地创建一个运行到mysql连接限制的应用程序,但我不想忽视这个限制的事实。
答案 0 :(得分:6)
最好的方法是在应用启动时创建一次数据库,然后使用此句柄。另外,sql.DB
类型可以安全地同时使用,因此您甚至不需要使用互斥锁来锁定其使用。完成后,根据您的驱动程序,数据库句柄将自动重新连接,因此您不需要自己执行此操作。
答案 1 :(得分:-3)
我建议在init()上建立与数据库的连接。 为什么?因为init()保证在main()之前运行,你肯定想确保在实际工作开始之前就设置了db conf。
var db *sql.DB
func GetDb() (*sql.DB, error) {
db, err = sql.Open("mysql","dsn...")
if err != nil {
return nil, err
}
return db, nil
}
func init() {
db, err := GetDb()
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
}
我没有测试上面的代码,但它在技术上应该是这样的。