database/sql: Retry with a fresh connection after maxBadConnRetries

Previously if the connection pool was larger than maxBadConnRetries
and there were a lot of bad connections in the pool (for example if
the database server was restarted), a query might have failed with an
ErrBadConn unnecessarily.  Instead of trying to guess how many times
to retry, try maxBadConnRetries times and then force a fresh
connection to be used for the last attempt.  At the same time, lower
maxBadConnRetries to a smaller value now that it's not that important
to retry so many times from the free connection list.

Fixes #8834

Change-Id: I6542f151a766a658980fb396fa4880ecf5874e3d
Reviewed-on: https://go-review.googlesource.com/2034
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Marko Tiikkaja 2015-03-27 19:45:12 +01:00 committed by Brad Fitzpatrick
parent d5ef698142
commit c468f94672
3 changed files with 147 additions and 42 deletions

View file

@ -89,7 +89,10 @@ type fakeConn struct {
stmtsMade int
stmtsClosed int
numPrepare int
bad bool
// bad connection tests; see isBad()
bad bool
stickyBad bool
}
func (c *fakeConn) incrStat(v *int) {
@ -243,13 +246,15 @@ func (db *fakeDB) columnType(table, column string) (typ string, ok bool) {
}
func (c *fakeConn) isBad() bool {
// if not simulating bad conn, do nothing
if !c.bad {
if c.stickyBad {
return true
} else if c.bad {
// alternate between bad conn and not bad conn
c.db.badConn = !c.db.badConn
return c.db.badConn
} else {
return false
}
// alternate between bad conn and not bad conn
c.db.badConn = !c.db.badConn
return c.db.badConn
}
func (c *fakeConn) Begin() (driver.Tx, error) {
@ -466,7 +471,7 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
}
if hookPrepareBadConn != nil && hookPrepareBadConn() {
if c.stickyBad || (hookPrepareBadConn != nil && hookPrepareBadConn()) {
return nil, driver.ErrBadConn
}
@ -529,7 +534,7 @@ func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
return nil, errClosed
}
if hookExecBadConn != nil && hookExecBadConn() {
if s.c.stickyBad || (hookExecBadConn != nil && hookExecBadConn()) {
return nil, driver.ErrBadConn
}
@ -613,7 +618,7 @@ func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
return nil, errClosed
}
if hookQueryBadConn != nil && hookQueryBadConn() {
if s.c.stickyBad || (hookQueryBadConn != nil && hookQueryBadConn()) {
return nil, driver.ErrBadConn
}