]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: close connection if db.numOpen > db.maxOpen
authorJiong Du <londevil@gmail.com>
Tue, 30 Dec 2014 08:12:50 +0000 (16:12 +0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 7 Apr 2015 09:27:26 +0000 (09:27 +0000)
Bug Description:
When reduce db.maxOpen via db.SetMaxOpenConns, the unnecssary
connections won't been released until all other connections are free.

Fixes #9453

Change-Id: I9afb2e4b184139b31029ae53d7f5fd1fdb8d8d7e
Reviewed-on: https://go-review.googlesource.com/2200
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/database/sql/sql.go
src/database/sql/sql_test.go

index b0e889467399486eb94794c91222cce5a4769041..0a84163a03d71d6c1398ec811036a3d71ee4ba89 100644 (file)
@@ -782,6 +782,9 @@ func (db *DB) putConn(dc *driverConn, err error) {
 // If a connRequest was fulfilled or the *driverConn was placed in the
 // freeConn list, then true is returned, otherwise false is returned.
 func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
+       if db.maxOpen > 0 && db.numOpen > db.maxOpen {
+               return false
+       }
        if c := len(db.connRequests); c > 0 {
                req := db.connRequests[0]
                // This copy is O(n) but in practice faster than a linked list.
index e225ffe6fa74dc967f51dea08b84c888374f12cf..45554c6d2d6855ef6456d7e29e9ce09f78267cb0 100644 (file)
@@ -1070,6 +1070,57 @@ func TestMaxOpenConns(t *testing.T) {
        }
 }
 
+// Issue 9453: tests that SetMaxOpenConns can be lowered at runtime
+// and affects the subsequent release of connections.
+func TestMaxOpenConnsOnBusy(t *testing.T) {
+       defer setHookpostCloseConn(nil)
+       setHookpostCloseConn(func(_ *fakeConn, err error) {
+               if err != nil {
+                       t.Errorf("Error closing fakeConn: %v", err)
+               }
+       })
+
+       db := newTestDB(t, "magicquery")
+       defer closeDB(t, db)
+
+       db.SetMaxOpenConns(3)
+
+       conn0, err := db.conn()
+       if err != nil {
+               t.Fatalf("db open conn fail: %v", err)
+       }
+
+       conn1, err := db.conn()
+       if err != nil {
+               t.Fatalf("db open conn fail: %v", err)
+       }
+
+       conn2, err := db.conn()
+       if err != nil {
+               t.Fatalf("db open conn fail: %v", err)
+       }
+
+       if g, w := db.numOpen, 3; g != w {
+               t.Errorf("free conns = %d; want %d", g, w)
+       }
+
+       db.SetMaxOpenConns(2)
+       if g, w := db.numOpen, 3; g != w {
+               t.Errorf("free conns = %d; want %d", g, w)
+       }
+
+       conn0.releaseConn(nil)
+       conn1.releaseConn(nil)
+       if g, w := db.numOpen, 2; g != w {
+               t.Errorf("free conns = %d; want %d", g, w)
+       }
+
+       conn2.releaseConn(nil)
+       if g, w := db.numOpen, 2; g != w {
+               t.Errorf("free conns = %d; want %d", g, w)
+       }
+}
+
 func TestSingleOpenConn(t *testing.T) {
        db := newTestDB(t, "people")
        defer closeDB(t, db)