Go链接MySql数据库too many connections

Go中链接数据库的链接池:当你须要和数据库通讯时,就会从链接池里面取出一个链接,和数据库交互。使用完的闲置的链接会回到链接池,等待下一次的调用。若是链接池里面没有闲置的链接,会自动建立一个新的链接出来。其中有一段:php

An sql.Row returns the connection when Scan() is called, sql.Rows returns either when Close() is called or all rows have been iterated over with Next(), and sql.Tx will return when Commit or Rollback() are called. If you forget to completely iterate an sql.Rows and you forget to Close it, that connection will never go back to the pool.golang

       从上面能够看到,sql.Row若是不遍历完或者直接调用Close()方法,执行此次查询的链接就会一直存在!当链接池里的可用链接用光后,就开始建立新的链接。这就是为何调用SetMaxOpenConns没有用的缘由,由于这个函数只是设置链接池里的链接数而已!若是由于不及时释放链接而让链接池干掉了,仍是会不断的建立新的链接,直到用光MySql全部的链接,报错。明白之后,在全部调用DB.Query的函数里加上了:web

defer row.Close()

        这样查询链接就能在函数结束或者异常的状况下被关闭,就不会持续建立新的链接了。满觉得这样就能够解决问题了,可是服务器运行了之后,过段时间仍然会出现相同的错误。在phpMyadmin里的监控页面,能够看到程序运行之后MySql的链接数猛增。问题又变得无解了,只能从新一行行检查代码。
sql

        Go中的函数能够有多个返回值,使用下划线能够忽略不须要的返回值:
数据库

_, err := m.DB.Query("sql")

        程序中update和del之类的sql语句不须要返回值,就直接忽略了。猜测这样也是无法释放链接的,由于即便你不接受返回值,不表明这个变量就不存在了。也就是说返回的sql.Row仍是存在的,只是你没有接收而已。没接收,就更谈不上释放链接了,因此最后产生了大量的链接继续报错。回头看看那篇文章,看到这么一段:
服务器

Ping and Exec will release the connection right before returning, but the others will pass ownership of the connection to the result, whether that's an sql.Row, sql.Rows, or sql.Tx.app

        也就是说Ping和Exec方法在调用完以后,会自动释放链接。把代码中全部不须要返回值的语句改为由Exce方法执行,go run 一下,ok,链接数终于正常了!
函数

        问题是解决了,总起来之后要注意一下的东西:
ui

  • 程序链接数据库会有链接泄漏的状况,须要及时释放链接url

  • Go sql包中的Query和QueryRow两个方法的链接不会自动释放链接,只有在遍历完结果或者调用close方法才会关闭链接

  • Go sql中的Ping和Exec方法在调用结束之后就会自动释放链接

  • 忽略了函数的某个返回值不表明这个值就不存在了,若是该返回值须要close才会释放资源,直接忽略了就会致使资源的泄漏。

  • 有close方法的变量,在使用后要及时调用该方法,释放资源

相关文章
相关标签/搜索