# How the Go MySQL Driver Detects Stale Connections in the Connection Pool

> Learn how go-sql-driver/mysql detects stale connections using driver interfaces and liveness probes to maintain a reliable connection pool and discard unusable connections.

- Repository: [Go SQL Drivers/mysql](https://github.com/go-sql-driver/mysql)
- Tags: internals
- Published: 2026-03-02

---

**The `go-sql-driver/mysql` detects stale or dead connections by implementing the `driver.SessionResetter` and `driver.Validator` interfaces, using a non-blocking socket probe in `ResetSession` to verify liveness before reuse, and returning `driver.ErrBadConn` to signal the pool to discard unusable connections.**

The `go-sql-driver/mysql` package leverages Go’s standard `database/sql` connection pool for connection management, but it supplies critical lifecycle hooks that enable proactive detection of broken TCP sockets. By understanding how the driver validates connection health before handing connections back to your application, you can configure resilient database clients that automatically survive network interruptions and MySQL server timeouts.

## The ResetSession Hook and Liveness Probing

When the `database/sql` pool retrieves a cached connection for reuse, it invokes the driver’s `ResetSession` method, which implements the `driver.SessionResetter` interface. In [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go) (lines 96–119), this method checks the `CheckConnLiveness` configuration flag before allowing the connection to proceed.

If `CheckConnLiveness` is `true` (the default), the driver executes a liveness probe via the `connCheck` function. This function performs a **non-blocking read operation** on the underlying network socket to determine if the connection is still viable. The probe operates exclusively on Linux and Darwin systems, where it can interact directly with socket file descriptors.

### Low-Level Socket Verification in connCheck

The `connCheck` implementation in [`conncheck.go`](https://github.com/go-sql-driver/mysql/blob/main/conncheck.go) (lines 23–55) attempts a zero-byte read with `MSG_PEEK` to check the socket state without consuming data. The logic interprets the system call result as follows:

- **EOF returned**: The socket is dead; the connection has been closed by the server or network.
- **`EAGAIN` or `EWOULDBLOCK` returned**: The socket is alive but has no data available, which is the expected state for an idle connection.
- **Any other error**: Treated as a failure indicating the connection is unusable.

When `connCheck` detects a dead socket, `ResetSession` returns `driver.ErrBadConn`. The `database/sql` pool interprets this error as a signal to discard the cached connection and establish a fresh one, ensuring your application never receives a broken socket.

## The IsValid Validator Hook

Beyond the session reset hook, the driver also implements the `driver.Validator` interface via the `IsValid` method in [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go) (lines 124–128). The pool may call this method to quickly verify connection state without performing a full network probe.

The `IsValid` implementation checks two conditions:
- Whether the connection has been explicitly closed.
- Whether the buffer is currently marked as busy via `buf.busy()`.

If either condition is true, the method returns `false`, prompting the pool to remove the connection from the cache immediately.

## Configuration and Error Handling

The liveness check behavior is controlled by the `checkConnLiveness` DSN parameter, defined in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go) (lines 62–68). The `NewConfig` function in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go) (lines 96–98) sets this flag to `true` by default, meaning stale connection detection is active unless explicitly disabled.

When the driver encounters any error during the liveness verification, it wraps the error as `driver.ErrBadConn`. This standardized error type allows the `database/sql` pool to distinguish between transient query failures (which might be retried on the same connection) and fundamental connection corruption (which requires eviction and replacement).

## Practical Implementation Examples

### Example 1: Default Stale Connection Detection

By default, the driver enables liveness checks without requiring explicit configuration. The pool automatically verifies connections on reuse.

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

func main() {
    // DSN without explicit checkConnLiveness uses the default (true)
    dsn := "user:pass@tcp(127.0.0.1:3306)/dbname"
    db, _ := sql.Open("mysql", dsn)

    // The pool invokes ResetSession on each reused connection.
    // Dead sockets trigger driver.ErrBadConn, causing automatic replacement.
}

```

### Example 2: Disabling Liveness Checks

You can disable the probe by setting `checkConnLiveness=false` in the DSN. This eliminates the overhead of the socket read but risks handing stale connections to your application.

```go
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?checkConnLiveness=false"
db, _ := sql.Open("mysql", dsn)

// The pool skips the connCheck probe. Use only in reliable network
// environments where you want to avoid the extra read-deadline overhead.

```

### Example 3: Pool Sizing with Stale Connection Handling

Configure pool limits to work in concert with the driver’s detection mechanisms. Dead idle connections are purged when detected during reuse, so you can allow indefinite connection lifetimes while maintaining reliability.

```go
db.SetMaxIdleConns(10)      // Maintain up to 10 idle connections
db.SetMaxOpenConns(50)      // Maximum total connections
db.SetConnMaxLifetime(0)    // Connections live indefinitely unless flagged bad

```

## Summary

- **`ResetSession` hook**: Called by the pool before reuse; triggers the liveness probe in [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go).
- **`connCheck` probe**: Performs non-blocking socket reads in [`conncheck.go`](https://github.com/go-sql-driver/mysql/blob/main/conncheck.go) to detect EOF or errors on Linux/Darwin.
- **`IsValid` validator**: Provides fast state checks via [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go) to detect closed or busy connections.
- **Error signaling**: Returns `driver.ErrBadConn` to force pool eviction of dead connections.
- **Configurable behavior**: Controlled by `checkConnLiveness` DSN flag (default `true`) defined in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go).

## Frequently Asked Questions

### How does the MySQL driver determine if a connection is stale?

The driver uses the `connCheck` function in [`conncheck.go`](https://github.com/go-sql-driver/mysql/blob/main/conncheck.go) to perform a non-blocking read on the socket file descriptor. If the read returns EOF, the connection is dead. If it returns `EAGAIN` or `EWOULDBLOCK`, the socket is alive. This check runs inside the `ResetSession` method (implemented in [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go)) whenever the pool prepares to reuse a connection.

### What happens when the driver detects a dead connection?

When `connCheck` detects a dead socket or `IsValid` finds the connection closed, the driver returns `driver.ErrBadConn`. The `database/sql` pool recognizes this error, discards the connection from the cache, and creates a new connection for the operation. This process is transparent to the application, which receives a fresh connection without explicit retry logic.

### Can I disable the automatic stale connection detection?

Yes. Set the DSN parameter `checkConnLiveness=false` to skip the `connCheck` probe. This reduces overhead but increases the risk of your application receiving a broken connection from the pool. Disable this only when operating in highly reliable network environments where socket deaths are extremely rare.

### Does the liveness check work on all operating systems?

No. The `connCheck` implementation relies on platform-specific socket operations and is only available on Linux and Darwin (macOS). On other operating systems, the driver falls back to the `IsValid` validator and relies on write errors during query execution to detect stale connections, though the `ResetSession` logic will still run if `CheckConnLiveness` is enabled.