How go-sql-driver/mysql Implements driver.Validator and driver.SessionResetter

The go-sql-driver/mysql package implements both interfaces on its internal *mysqlConn type in connection.go, using IsValid() to check atomic closed flags and buffer status, and ResetSession() to perform optional TCP liveness checks when connections are retrieved from the pool.

The github.com/go-sql-driver/mysql driver enhances Go's connection pooling by implementing the optional driver.Validator and driver.SessionResetter interfaces from the standard library's database/sql/driver package. These implementations, located in the driver's core connection management logic, enable efficient stale connection detection and automatic pool maintenance without requiring application-level intervention.

Overview of the Connection Interfaces

The driver satisfies both optional interfaces on its internal *mysqlConn struct defined in connection.go. This type holds the network socket, a buffered writer (buf), an atomic closed flag, and the parsed DSN configuration (cfg). By implementing these interfaces, the driver allows database/sql to validate pooled connections before reuse and discard stale connections without expensive network round-trips.

Implementing the driver.Validator Interface

The driver.Validator interface enables the connection pool to check whether a connection is still valid before returning it to the application. According to the source code in connection.go lines 23-27, the implementation is straightforward and lightweight.

The IsValid Method

The IsValid() method returns true only when the connection is open and not busy:

func (mc *mysqlConn) IsValid() bool {
    return !mc.closed.Load() && !mc.buf.busy()
}

mc.closed is an atomic flag set when Close is called, while mc.buf.busy() reports whether the driver is currently sending a command. This ensures the connection is not mid-operation when the pool checks its validity, preventing the reuse of connections in an inconsistent state.

Implementing the driver.SessionResetter Interface

The driver.SessionResetter interface is invoked each time a connection is retrieved from the pool, allowing the driver to reset session state or verify liveness. As implemented in connection.go lines 89-121, the ResetSession method performs lightweight checks and optional TCP-level pings.

The ResetSession Method Logic

func (mc *mysqlConn) ResetSession(ctx context.Context) error {
    if mc.closed.Load() || mc.buf.busy() {
        return driver.ErrBadConn
    }
    if mc.cfg.CheckConnLiveness {
        conn := mc.netConn
        if mc.rawConn != nil {
            conn = mc.rawConn
        }
        var err error
        if mc.cfg.ReadTimeout != 0 {
            err = conn.SetReadDeadline(time.Now().Add(mc.cfg.ReadTimeout))
        }
        if err == nil {
            err = connCheck(conn)
        }
        if err != nil {
            mc.log("closing bad idle connection: ", err)
            return driver.ErrBadConn
        }
    }
    return nil
}

The method first guards against closed or busy connections, returning driver.ErrBadConn immediately if either condition is met. When the DSN option checkConnLiveness is enabled, it performs a read-deadline-based ping using the connCheck function from conncheck.go. If the ping fails, the method returns driver.ErrBadConn, signaling the pool to discard the connection.

Compile-Time Interface Verification

To ensure the implementation remains synchronized with the standard library interfaces, the driver includes compile-time assertions at the bottom of connection.go (lines 29-30):

var _ driver.SessionResetter = &mysqlConn{}
var _ driver.Validator      = &mysqlConn{}

These lines guarantee that *mysqlConn satisfies both interfaces. If the method signatures ever drift from the standard library requirements, the code will fail to compile, maintaining contract integrity.

Practical Usage Examples

These interfaces operate automatically when using database/sql, but understanding their behavior helps configure optimal connection pool settings.

Automatic Pool Management via database/sql

When using the driver through the standard database/sql package, the interfaces are invoked automatically during connection checkout. Enable liveness checking by adding checkConnLiveness=1 to your DSN:

package main

import (
    "database/sql"
    "log"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname?checkConnLiveness=1"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatalf("Open: %v", err)
    }
    defer db.Close()

    if err := db.Ping(); err != nil {
        log.Fatalf("Ping: %v", err)
    }
    
    rows, err := db.Query("SELECT 1")
    if err != nil {
        log.Fatalf("Query: %v", err)
    }
    rows.Close()
}

When db.Ping() or any query executes, the pool retrieves a connection and calls ResetSession. If the connection is stale, the driver returns driver.ErrBadConn, prompting the pool to discard it and open a fresh TCP socket.

Direct Interface Access for Testing

While rarely needed in production, you can access these methods directly by casting the concrete connection type:

package main

import (
    "context"
    "fmt"
    "github.com/go-sql-driver/mysql"
)

func main() {
    cfg, _ := mysql.ParseDSN("user:pwd@tcp(localhost:3306)/db")
    conn := mysql.NewConnector(cfg)
    dconn, _ := conn.Connect(context.Background())
    mc := dconn.(*mysql.mysqlConn)

    fmt.Println("IsValid:", mc.IsValid())
    fmt.Println("ResetSession:", mc.ResetSession(context.Background()))
}

This approach bypasses the pool management and allows direct validation of connection states during driver development or debugging scenarios.

Summary

  • The go-sql-driver/mysql implements driver.Validator and driver.SessionResetter on the *mysqlConn type in connection.go.
  • IsValid() checks atomic closed flags and buffer busy status to prevent reuse of mid-operation connections.
  • ResetSession() performs lightweight liveness verification when checkConnLiveness is enabled, returning driver.ErrBadConn for stale connections.
  • Compile-time assertions in connection.go ensure interface compliance with the standard library.
  • These implementations enable database/sql to maintain healthy connection pools automatically without application intervention.

Frequently Asked Questions

How do I enable connection liveness checking in go-sql-driver/mysql?

Add checkConnLiveness=1 to your DSN configuration. This activates the TCP-level ping inside ResetSession that validates connections when they are retrieved from the pool. Without this flag, ResetSession only checks the closed and busy flags without network verification.

What happens when ResetSession returns driver.ErrBadConn?

The database/sql package automatically discards the connection and attempts to retrieve or create a new one. This error signals that the connection is no longer usable, prompting the pool to refresh its resources without exposing the stale connection to your application code.

Why does IsValid check both closed and busy flags?

The closed atomic flag indicates whether Close() has been called on the connection, while buf.busy() reports whether a command is currently being transmitted. Checking both prevents the pool from reusing a connection that is either terminally closed or in the middle of a network operation, ensuring state consistency.

Where are these interfaces defined in the source code?

Both implementations reside in connection.go. The IsValid method appears at lines 23-27, ResetSession at lines 89-121, and the compile-time interface assertions at lines 29-30. The TCP liveness check used by ResetSession is implemented in conncheck.go.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →