在
go
中,我遇到了sql.DB
的连接池堆积了如此多的连接,以至于达到了odbc驱动程序的限制的问题。连接应该自动关闭,但这永远不会发生。
所以我想看看当我专门请求连接、执行查询并最终关闭它以将其返回到池时会发生什么。 以下代码卡在最后的
err = conn.Close()
行。有人能弄清楚为什么吗?
package main
import (
"database/sql"
"log"
"github.com/gin-gonic/gin"
)
var db *sql.DB
func main() {
db, err := sql.Open("odbc", "DSN=ADSconnStr")
if err != nil {
log.Fatal(err)
return
}
err = db.Ping()
if err != nil {
log.Fatal(err)
return
}
router := gin.Default()
router.GET("test/url", testQuery)
log.Fatal(router.Run(":8080"))
err = db.Close()
if err != nil {
log.Fatal(err)
}
}
func testQuery(c *gin.Context) {
ctx := c.Copy()
conn, err := db.Conn(ctx)
if err != nil {
log.Fatal(err)
return
}
rows, err := conn.QueryContext(ctx, "SELECT * FROM testTable;")
if err != nil {
log.Fatal(err)
return
}
// scan results ...
err = rows.Close()
if err != nil {
log.Fatal(err)
return
}
// here it gets stuck. conn.Close never returns
err = conn.Close()
if err != nil {
log.Fatal(err)
return
}
}
我发现了问题:
在
sql.Open("odbc", "DSN=ADSconnStr")
中,我建立了与旧 sql 数据库管理系统(Advantage Database Server)的连接。这个 DBMS 具有这样的“功能”,只要还存在任何(缓存的?)对象,它就可以强烈地让您不会断开连接。即>准备好的报表<. They must be closed.
以下代码有效。也许可以缩短它,但我明确想关闭连接。
func testADS(c *gin.Context) {
conn, err := db.Conn(context.Background())
if err != nil {
log.Panic("no connection")
}
tx, err := conn.BeginTx(context.Background(), nil)
if err != nil {
log.Panic("no transaction")
}
stmt, err := tx.Prepare("SELECT some_code FROM testTable")
if err != nil {
log.Panic("no prepared statement")
}
rows, err := stmt.Query()
if err != nil {
log.Panic("no rows")
}
if !rows.Next() {
log.Panic("no next row")
}
var code string
err = rows.Scan(&code)
if err != nil {
log.Panic("no scan")
}
log.Printf("Code: %s", code)
err = tx.Commit()
if err != nil {
log.Panic("no commit")
}
err = rows.Close()
if err != nil {
log.Panic("no rows close")
}
err = stmt.Close()
if err != nil {
log.Panic("no stmt close")
}
// now that the statement is closed the connection can be closed finally
err = conn.Close()
if err != nil {
log.Panic("no conn close")
}
// log.Celebrate("Yay :)")
}