【问题标题】:Issue with connections pool on mysqlmysql上的连接池问题
【发布时间】:2022-05-09 19:34:52
【问题描述】:

我正在开发的 api 遇到一些问题:有时(是的,并非总是如此)当我从我的 Angular 应用程序向 golang 服务器发出请求时,它给了我这个错误:“sql: database is closed " 当我试图执行“QueryContext”时,但我认为它更频繁地发生在从数据库请求更大数据的函数上(200 条记录顶部)。

有没有办法检查连接是否仍然打开\有效? golang的连接池不应该自动做吗? (我在具有相同数据库的同一服务器中还有其他更“轻”的 API,并且一切正常)

有什么我应该改变的MySql设置吗?(mysql有默认设置)

golang 版本:1.16, mysql 8.0.17

Hre 是我的代码示例: 在包 database.go 上

func OpenConnection() (*sql.DB, error)
{
    connection, err = sql.Open("mysql", "root@/my_database")
    if err != nil {
        log.Println("Error opening the connection with the database")
        return nil, err
    }
    return connection, nil
}

在 main.go 上

func main() {
    ---
    http.HandleFunc("/apicall1", customFunc)
    http.HandleFunc("/apicall2", customFunc)
    http.HandleFunc("/apicall3", customFunc)
}
func customFunc(w http.ResponseWriter, r *http.Request) {
    conn, err := database.OpenConnection()
    if err != nil {
        //handle error 500 response
    }
    defer conn.Close()
    switch(r.URL.Path) {
    case "url1": my_package.Func1(conn)
    case "url2": my_package.Func2(conn)
    case "url3": my_package.Func3(conn)
    ...
    default: //handle not found response
    }
}

【问题讨论】:

  • 你的 Go 代码在哪里?
  • Matteo 你打开了太多的连接。您的应用程序通常应该只打开一个 *sql.DB 并在应用程序的整个生命周期中使用它。即在每个处理程序中为每个请求调用 OpenConnection 是 badstackoverflow.com/questions/50787804/…
  • sql.Open 上的文档说:“返回的 DB 对于多个 goroutine 并发使用是安全的,并维护自己的空闲连接池。因此,Open 函数应该是只调用一次。很少需要关闭数据库。"
  • 但是!您必须 Close 每个返回的 *sql.Rows。您必须 Scan 每个返回的 *sql.Row。您必须 CommitRollback 每个 *sql.Tx。而且你必须 Close 每一个 *sql.Stmt 你不会再使用。
  • 好的,所以我必须在 http.HandleFunc 之前移动 main func 中的开口。对于 *sql.Rows 和其他所有内容,我肯定会关闭它,但我会检查

标签: mysql api go


【解决方案1】:

您需要配置 sql.DB 以获得更好的池性能并避免达到 db 允许连接的最大限制,这里作为示例,我设置了最大 100 个连接和空闲 25 个,您可以根据负载进行更改.另外,在连接成功后 ping db 也是一个好主意,只是为了确保连接成功。

func OpenConnection() (*sql.DB, error)
{
    connection, err = sql.Open("mysql", "root@/my_database")
    if err != nil {
        log.Println("Error opening the connection with the database")
        return nil, err
    }
    connection.DB().SetMaxIdleConns(25)
    connection.DB().SetMaxOpenConns(100)
    dberr = connection.DB().Ping()
    if dberr != nil {
        log.Println("failed to ping db repository : %s", dberr)
        return nil, dberr
    }
    return connection, nil
}

参考 - https://www.alexedwards.net/blog/configuring-sqldb

【讨论】:

    猜你喜欢
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 2011-07-08
    • 2011-04-01
    • 2012-09-25
    • 2011-04-23
    • 1970-01-01
    相关资源
    最近更新 更多