我正在使用github.com/go-sql-driver/mysql驱动程序。
我打开一个数据库:
db, err := sql.Open("mysql", str)
然后我有两个函数,每个函数被调用200次,后面跟着mysql代码:
rows, err := db.Query("select name from beehives")
if err != nil {
panic(err)
}
defer rows.Close()
第二个:
err = db.QueryRow("select id, secret, shortname from beehives where shortname = ?", beehive).Scan(&id, &secre
switch {
case err == sql.ErrNoRows:
err = errors.New("Beehive '"+beehive+"' not found.")
case err != nil:
panic("loginBeehive: "+ err.Error())
default:
// ... do the work
第一个是慌乱。
当我只打开一次数据库时,怎么会有多个连接?如何关闭它们?
答案 0 :(得分:22)
sql.Open doesn't really open a connection to your database.
sql.DB维护与数据库的连接池。每次查询数据库时,程序都会尝试从此池中获取连接,否则将创建一个新的连接。一旦你关闭它们,这些连接就会被放回池中。
这是rows.Close()
的作用。
当您致电db.QueryRow("...")
时,Scan(...)
会在内部做同样的事情。
基本问题是您创建了太多查询,其中每个查询都需要连接,但您没有足够快地关闭连接。这样,您的程序必须为每个查询创建一个新连接。
您可以通过调用sql.DB上的SetMaxOpenConns来限制程序使用的最大连接数。
有关详细信息,请参阅http://go-database-sql.org/surprises.html。
答案 1 :(得分:6)
您从*DB
返回的sql.Open
对象与单连接不对应。最好将其视为数据库的句柄:它为您管理连接池。
您可以使用`(*DB).SetMaxOpenConns和its pair来控制空闲连接的打开连接数。
所以基本上这里发生的是db.Query
和db.QueryRow
尝试为自己获取连接,并且DB句柄不会对同时连接的数量施加任何限制,因此您的代码会引起恐慌当它打开超过mysql可以处理的内容时。
答案 2 :(得分:3)
尝试制作准备好的语句db.Prepare(query string) (*Stmt, error)
而不是stmt.Query
或stmt.Exec
而不是stmt.Close
来重复使用连接。
答案 3 :(得分:0)
我的程序始终连接到数据库。 (出勤的实时面部识别)
因此,打开和关闭数据库连接毫无用处。
因此,它仅在初始化程序的情况下才打开数据库连接。
func GetAllFaces() interface{} {
OpenDatabaseConnection() ...
}
但是稍后访问数据库,增加了连接数,并导致程序崩溃。但是关闭rows
对象不会使活动连接最少。 (对我来说1)
func SaveAttendance(faceId int, date time.Time) error {
sqlQuery := fmt.Sprintf("SELECT ... "))
rows, err := DB.Query(sqlQuery) ...
err = rows.Close()
return err
}
答案 4 :(得分:0)
嗨,您可以在使用后尝试关闭连接
db, err := sql.Open("mysql", str)
defer db.Close() // close after end scope