Golang:即使数据库关闭,Ping也会第二次成功 [英] Golang: Ping succeed the second time even if database is down

查看:137
本文介绍了Golang:即使数据库关闭,Ping也会第二次成功的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个有趣的问题,即db.Ping()不会返回错误,即使数据库自第一次尝试以来已经被终止。



源代码如下:

  import(
database / sql
fmt
log
time

_github.com/go-sql-driver/mysql


类型数据库结构{
datasource string
conn * sql.DB
}

// Connect创建并初始化一个数据库struct
func(db * database)Connect(server ,用户名,密码,DBPort字符串)错误{
var err错误

db.datasource = fmt.Sprintf(%s:%s @ /,用户,密码)
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(等待15秒,杀死数据库)
< -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版本go1.7.1 linux / amd64



预先感谢!

解决方案

在第一次连接后,Ping实际上不会ping数据库。这很奇怪,也是错误的,但这是它的工作方式(直到转到1.8 )。如果连接池中现有的连接尚未超时,Ping就会将其从池中移除并返回给您,而实际上并不打算检查数据库是否仍然存在。



Kardianos(编写上述链接文档以及Govendor)在1.8版中对此进行了修正,前提是数据库驱动程序支持它。然而,在此之前,Ping对于确定数据库是否仍然存在并不可靠。


I have run into an interesting issue, namely, that db.Ping() does not return an error even if the database has been killed since the first attempt.

Source code below:

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
}

At first, the database is up, so the first Ping succeeds. However, I put a delay in there just for the sake of testing. In that 15 seconds I stop the database (sudo service mysql stop), however, db.Ping() still succeeds.

If I were to execute any actual query (via db.Query, db.QueryRow or db.Exec), then the sql package would panic with Broken Pipe (which is expected).

Am I doing something wrong?

also: go version go1.7.1 linux/amd64

Thanks in advance!

解决方案

Ping, after the first connection, doesn't actually ping the database. It's odd, and wrong, but that's the way it works (until Go 1.8). If there's an existing connection in the connection pool that hasn't timed out, Ping will simply remove it from the pool and return it to you, without actually bothering to check if the database is still there.

Kardianos (who wrote the above linked document, as well as Govendor) fixed this in 1.8, provided the database driver supports it. Until then, however, Ping isn't reliable for determining if the database is still there.

这篇关于Golang:即使数据库关闭,Ping也会第二次成功的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆