【问题标题】:Golang, mysql: Error 1040: Too many connectionsGolang,mysql:错误1040:连接太多
【发布时间】:2015-03-24 00:11:06
【问题描述】:

我正在使用 github.com/go-sql-driver/mysql 驱动程序。

我打开一个数据库:

db, err := sql.Open("mysql", str)

然后我有两个函数,每个函数被调用 200 次,使用以下 mysql 代码:

rows, err := db.Query("select name from beehives")
if err != nil {
    panic(err)
}       
defer rows.Close()

第二个:

    err = db.QueryRow("select id, secret, shortname from beehives where shortname = ?", beehive).Scan(&id, &secre
    switch {
    case err == sql.ErrNoRows:
        err = errors.New("Beehive '"+beehive+"' not found.")
    case err != nil:
        panic("loginBeehive: "+ err.Error())
    default:
        // ... do the work

第一个是恐慌的。

我只打开一次数据库怎么会有多个连接,如何关闭它们?

【问题讨论】:

  • 正好遇到这个问题,非常感谢您的提问!

标签: mysql go


【解决方案1】:

sql.Open doesn't really open a connection to your database.

sql.DB 维护一个与您的数据库的连接池。每次查询数据库时,您的程序都会尝试从该池中获取连接,否则会创建一个新连接。一旦你关闭它们,这些连接就会被放回池中。

这就是rows.Close() 所做的。 当您致电 Scan(...) 时,您的 db.QueryRow("...") 在内部执行相同的操作。

基本问题是您创建了太多查询,每个查询都需要一个连接,但您关闭连接的速度不够快。这样,您的程序必须为每个查询创建一个新连接。

您可以通过在 sql.DB 上调用 SetMaxOpenConns 来限制程序使用的最大连接数。

更多信息请参见http://go-database-sql.org/surprises.html。

【讨论】:

  • 我们的生产系统也遇到了同样的问题。后来我们找到了这个帖子并尝试了它。它起作用了,因为每个连接都占用了我们的主内存空间。然后我们配置了 SQL server 并设置连接过期时间为 1 秒。谢谢,你铺平了道路@nussjustin
【解决方案2】:

您从sql.Open 返回的*DB 对象与单个 连接不对应。最好将其视为数据库的句柄:它为您管理一个连接池。

您可以使用`(*DB).SetMaxOpenConns 和its pair 控制空闲连接的打开连接数。

所以基本上这里发生的情况是db.Query 和db.QueryRow 尝试为自己获取连接,并且数据库句柄对同时连接的数量没有任何限制,因此当它打开的次数超过mysql可以处理。

【讨论】:

    【解决方案3】:

    尝试使准备好的语句db.Prepare(query string) (*Stmt, error) 和stmt.Query 或stmt.Exec 和stmt.Close 重复使用连接。

    【讨论】:

      【解决方案4】:

      你好,使用后可以尝试关闭连接

      db, err := sql.Open("mysql", str)
      defer db.Close() // close after end scope
      

      【讨论】:

        【解决方案5】:

        我的程序总是连接到数据库。 (考勤实时人脸识别)

        因此打开和关闭数据库连接是没有价值的。

        因此它只在初始化程序时保持打开数据库连接。

        func GetAllFaces() interface{} {
            OpenDatabaseConnection() ... 
        }
        

        但后来访问数据库,增加了连接数,导致程序崩溃。但是关闭rows 对象至少不会保持活动连接。 (对我来说 1)

         func SaveAttendance(faceId int, date time.Time) error {
            sqlQuery := fmt.Sprintf("SELECT ... "))
        
            rows, err := DB.Query(sqlQuery) ...
            err = rows.Close()
            return err
        }
        

        【讨论】:

          猜你喜欢
          • 2017-10-30
          • 2012-12-29
          • 2020-04-27
          • 2014-06-27
          • 2015-08-06
          • 1970-01-01
          • 2019-07-15
          • 2018-12-22
          • 2019-04-29
          相关资源
          最近更新 更多