Go连接MySql数据库too many connections
2019獨角獸企業重金招聘Python工程師標準>>>
Go中連接數據庫的連接池:當你需要和數據庫通信時,就會從連接池里面取出一個連接,和數據庫交互。使用完的閑置的連接會回到連接池,等待下一次的調用。如果連接池里面沒有閑置的連接,會自動創建一個新的連接出來。其中有一段:
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.
???????從上面可以看到,sql.Row如果不遍歷完或者直接調用Close()方法,執行這次查詢的連接就會一直存在!當連接池里的可用連接用光后,就開始創建新的連接。這就是為什么調用SetMaxOpenConns沒有用的原因,因為這個函數只是設置連接池里的連接數而已!如果因為不及時釋放連接而讓連接池干掉了,還是會不斷的創建新的連接,直到用光MySql所有的連接,報錯。明白以后,在所有調用DB.Query的函數里加上了:
defer?row.Close()????????這樣查詢連接就能在函數結束或者異常的情況下被關閉,就不會持續創建新的連接了。滿以為這樣就可以解決問題了,但是服務器運行了以后,過段時間仍然會出現相同的錯誤。在phpMyadmin里的監控頁面,可以看到程序運行以后MySql的連接數猛增。問題又變得無解了,只能重新一行行檢查代碼。
????????Go中的函數可以有多個返回值,使用下劃線可以忽略不需要的返回值:
? ? ????程序中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.
????????也就是說Ping和Exec方法在調用完之后,會自動釋放連接。把代碼中所有不需要返回值的語句改成由Exce方法執行,go run 一下,ok,連接數終于正常了!
????????問題是解決了,總起來以后要注意一下的東西:
程序連接數據庫會有連接泄漏的情況,需要及時釋放連接
Go sql包中的Query和QueryRow兩個方法的連接不會自動釋放連接,只有在遍歷完結果或者調用close方法才會關閉連接
Go?sql中的Ping和Exec方法在調用結束以后就會自動釋放連接
忽略了函數的某個返回值不代表這個值就不存在了,如果該返回值需要close才會釋放資源,直接忽略了就會導致資源的泄漏。
有close方法的變量,在使用后要及時調用該方法,釋放資源
轉載于:https://my.oschina.net/u/567830/blog/425529
總結
以上是生活随笔為你收集整理的Go连接MySql数据库too many connections的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL Windows ZIP 免费
- 下一篇: NoMasp博客导读