数据库连接最佳实践

时间:2014-07-25 08:40:49

标签: go

我有一个使用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连接限制的应用程序,但我不想忽视这个限制的事实。

2 个答案:

答案 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)
   }
}

我没有测试上面的代码,但它在技术上应该是这样的。