记一次gorm连接池打满,连接不释放的问题
概述:使用事务一定要关闭!
我们golang项目用的gorm,最近pre测试跑脚本时,总会出现504,某个接口不可用。分析了半天pprof,阻塞数量较多的goroutine,某些时候并不能看到真实问题的所在。
出现504,通过pprof:debug/pprof/goroutine?debug=2 或者debug/pprof/goroutine?debug=1 能看到阻塞的goroutine,处在io wait状态
检查下pod内,连接数(netstat),发现http的连接数和mysql的连接数暴增!!!
导致mysql的连接数暴增常见的有三种:
1、使用事务,没有关闭~!!!!! (我们小伙伴的错误命中)
tx:=db.conn后,err判断,直接return,没有进行tx.rollback。这时候mysql的conn_pool会+1,且不可复用。
错误的请求继续上涨后,就会出现连接数打满,继而新的请求一直阻塞,goroutine也会阻塞住。
此时杀死连接也没用,因为goroutine锁死在tx.awaitDone()里,也就是在等待done的chan返回。
只有调用tx.Commit或tx.Rollback才能使awaitDone返回,否则会造成conn闲置,协程溢出。
tx.Commit或tx.Rollback都会调用Tx.cancel和Tx.releaseConn。
正确使用:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
2、使用rows方法请一定要关闭连接。rows请一定要在err==nil的情况下使用,不然会导致空指针panic。
同样的协程等待Rows.awaitDone返回,需要通过Rows.Close调用Rows.cancel和Rows.releaseConn。
| 1 2 3 4 5 |
|
3、使用事务,切记使用新的tx变量
| 1 |
|