-
Notifications
You must be signed in to change notification settings - Fork 18k
database/sql: SetConnMaxIdleTime, SetConnMaxLifetime order impacts close time #45993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@Equinox76 both lines look the same? |
Thanks! Copy paste error which i corrected. |
I re-discovered this today and can add a little more context on how to reproduce it. I believe @eqinox76's examples are actually backwards. Setting Reproducing the bugTo trigger this bug, the following order of operations is required:
If this is the order of operations, then no idle connections will be closed until one Example code that triggers the bug: package main
// Import go-sql-driver and connect to a mysqL server and make a basic query
import (
"database/sql"
"fmt"
"time"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, _ := sql.Open("mysql", "root:@tcp(localhost:3306)/dbname")
// Create a connection
db.Ping()
db.SetConnMaxLifetime(1000 * time.Second)
db.SetConnMaxIdleTime(3 * time.Second)
stats := db.Stats()
fmt.Println("Open connections", stats.OpenConnections, "Idle connections", stats.Idle)
fmt.Println("Sleep")
// Should be long enough to clear idle connection
time.Sleep(5 * time.Second)
stats = db.Stats()
fmt.Println("Open connections", stats.OpenConnections, "Idle connections", stats.Idle)
} Expected output:
Actual Output:
WorkaroundsTo avoid the bug currently, either of the following changes will fix it:
db.SetConnMaxLifetime(1000 * time.Second)
db.SetConnMaxIdleTime(3 * time.Second)
CauseWhen a connection exists and https://github.com/golang/go/blob/master/src/database/sql/sql.go#L1046 Afterwards when we call https://github.com/golang/go/blob/master/src/database/sql/sql.go#L1034 Why the workarounds work: If there is no connection when we call these functions, then the cleaner is not started at all, and is only started after the first connection is allocated here, at which point it will use the lower https://github.com/golang/go/blob/master/src/database/sql/sql.go#L1521-L1523 Alternatively, calling |
The existing implementation wouldn't wake the connection cleaner if maxIdleTime was set to a value less than maxLifetime resulting in idle connections being held on to longer than expected. Fixes golang#45993
Change https://go.dev/cl/467655 mentions this issue: |
The existing implementation wouldn't wake the connection cleaner if maxIdleTime was set to a value less than maxLifetime resulting in idle connections being held on to longer than expected. Fixes golang#45993
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
When using
idle connections get closed after 5 hours. While setting the parameters in reverse order works fine.
What did you expect to see?
Closing idle connections after ~5s.
What did you see instead?
Closing connections after ~5h
I think this is due to sql.go#L1041 only checking if
maxIdleTime
has been reduced and not also if its smaller thanmaxLifetime
.The text was updated successfully, but these errors were encountered: