Skip to content

"invalid session pool" error when db.SetConnMaxLifetime is set #288

@elek

Description

@elek

Environment details

  • Programming language: go
  • OS: linux
  • Language runtime version: go version go1.23.0 linux/amd64
  • Package version: 1.7.0 (also tested with 1.6.)

Steps to reproduce

Looks like, if we set db.SetConnMaxLifetime, the session is invalidated after a while, and couldn't be used any more...

Go supposed to close the connection, but remove it from the free pool and replace it with a fresh one.

The following code (which just stes the ConnMaxLifetime and running the hello world) will fail eventually.

But not with pgx (cockroach). It works well, even if the connection / session is invalidated.

// Copyright 2021 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"context"
	"database/sql"
	"fmt"
	_ "github.com/googleapis/go-sql-spanner"
	_ "github.com/jackc/pgx/v5/stdlib"
	"time"
)

// Simple sample application that shows how to use the Spanner Go sql driver.
// Execute the sample with the command `go run main.go` from this directory.
func helloWorld() error {
	ctx := context.Background()
	// same thing with cockroach
	//db, err := sql.Open("pgx", "postgres://root@localhost:26257/env1?sslmode=disable")
	db, err := sql.Open("spanner", "projects/test-project/instances/test-instance/databases/db")
satellite")
	if err != nil {
		return fmt.Errorf("failed to open database connection: %v\n", err)
	}
	defer db.Close()
	db.SetConnMaxLifetime(time.Second * 20)

	for i := 0; i < 10000; i++ {
		err := selectOnce(ctx, db)
		if err != nil {
			return err
		}
		time.Sleep(1 * time.Second)
	}
	return nil
}

func selectOnce(ctx context.Context, db *sql.DB) error {
	rows, err := db.QueryContext(ctx, "SELECT 'Hello World!'")
	if err != nil {
		return fmt.Errorf("failed to execute query: %v", err)
	}
	defer rows.Close()

	var msg string
	for rows.Next() {
		if err := rows.Scan(&msg); err != nil {
			return fmt.Errorf("failed to scan row values: %v", err)
		}
		fmt.Printf("%s\n", msg)
	}
	if err := rows.Err(); err != nil {
		return fmt.Errorf("failed to execute query: %v", err)
	}
	return nil
}

func main() {
	err := helloWorld()
	if err != nil {
		panic(err)
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions