我遇到了一个有趣的问题,即即使数据库自第一次尝试以来已被杀死,db.Ping()也不会返回错误。
以下源代码:
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
type database struct {
datasource string
conn *sql.DB
}
// Connect creates and initialises a Database struct
func (db *database) Connect(server, user, password, DBPort string) error {
var err error
db.datasource = fmt.Sprintf("%s:%s@/", user, password)
db.conn, err = sql.Open(server, db.datasource)
if err != nil {
log.Fatal(err)
}
err = db.conn.Ping()
if err != nil {
db.conn.Close()
return err
}
log.Println("Waiting for 15 seconds, kill the DB")
<-time.After(15 * time.Second)
err = db.conn.Ping()
if err != nil {
db.conn.Close()
return err
}
log.Println("Second ping successful")
return nil
}
首先,数据库已启动,因此第一个Ping成功。但是,为了测试,我在那里放了一个延迟。在那15秒内我停止了数据库(sudo service mysql stop
),然而,db.Ping()仍然成功。
如果我要执行任何实际查询(通过db.Query
,db.QueryRow
或db.Exec
),那么sql包会因为Broken Pipe(预期)而发生恐慌。
我做错了吗?
另外:go go go版本1.7.1 linux / amd64
提前致谢!
答案 0 :(得分:9)
Ping,在第一次连接后,实际上并没有 ping数据库。这是奇怪的,也是错的,但这就是它的工作方式(直到Go 1.8)。如果连接池中存在尚未超时的现有连接,Ping将只是将其从池中删除并将其返回给您,而实际上并不打算检查数据库是否仍在那里。
Kardianos(编写上述链接文档以及Govendor)在1.8中修复此问题,前提是数据库驱动程序支持它。但是,在此之前,Ping不能确定数据库是否仍然存在。