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 關注
- 235 瀏覽
添加回答
舉報