Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang: Ping succeed the second time even if database is down

Tags:

sql

go

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!

like image 867
Daniel Javorszky Avatar asked Jan 12 '17 16:01

Daniel Javorszky


1 Answers

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.

like image 61
Kaedys Avatar answered Oct 20 '22 18:10

Kaedys