1 回答
TA贡献1757条经验 获得超8个赞
看来这不是 的错PingContext。tldr 跳到底部。
PingContext支持带有超时的上下文,但在调试时,似乎原因的根源是调用sql.Open(),或者其他一些调用,然后sql.Conn()是对 after 的调用PingContext。前两个获取db.mu.lock,在它PingContext有机会使用您的超时上下文之前最终等待: https://github.com/golang/go/blob/master/src/database/sql/sql.go#L1394
conn.PingContext当使用instead of 时变得更加清晰db.PingContext,例如对于阻塞的端口,超时是这样发生的:
db, err := sql.Open(driver, connStr)
if err != nil {
// This error will not happen
log.Fatalln(err)
}
// Create a 1 second timeout
ctxBG := context.Background()
ctxConnTimeout, cancel := context.WithTimeout(ctxBG, 1*time.Second)
defer cancel()
conn, err := db.Conn(ctxConnTimeout) // Hangs here for 60 seconds, never uses my timeout
if err != nil {
// This error fires
log.Fatalln(err)
}
// Never got here
ctxPingTimeout, cancel := context.WithTimeout(ctxBG, 1*time.Second)
defer cancel()
err = conn.PingContext(ctxPingTimeout)
if err != nil {
log.Fatalln(err)
}
那么如何将超时传递给sql.Openorsql.Conn呢?似乎这是唯一的方法:
sql.Open("mysql", "user:password@/dbname?timeout=5s")
sql.Open("postgres", "user=user dbname=dbname connect_timeout=5")
sql.Open("sqlserver", "sqlserver://username:password@host/instance?dial+timeout=5")
TA贡献1851条经验 获得超4个赞
我使用以下 MySQL DSN 格式在 2 秒内超时,它工作得很好。
user:password@tcp(localhost:80)/dbname?timeout=2s
- 1 回答
- 0 关注
- 173 浏览
添加回答
举报