gorm使用事务并发情况下切有最大mysql连接数限制的情况下的BUG,踩坑了
现象
服务器pprof中的goroutines 很多,无法释放,肯定是异常.
代码
// 收到 请求上个赛季个人秘境赛季排行
func (this *MsgProc) MsgProc_PersonSecretLastRankReq(msg *protoMsg.PersonSecretLastRankReq) {
global.GetSrvInst().GetThreadGo().Go(func(ctx context.Context) {
global.GetSrvInst().GetMysqlConn().Transaction(func(tx *gorm.DB) error {
// 拿到当前数据
var mynode *protoMsg.PersonSecretRankMD
global.GetSrvInst().GetMysqlConn().Where("seasonid=? and pid=?", msg.SeasonID, msg.PID).Find(&mynode)
if mynode == nil || mynode.SeasonID == 0 || mynode.PID == 0 {
// 空数据
server.PostPlayerSrv(msg.PID, gcommon.ServerTypeLobby, &protoMsg.PersonSecretLastRankRet{
LastSeasonID: msg.SeasonID,
PID: msg.PID,
LastSeasonRank: 0,
})
return nil
}
server.PostPlayerSrv(msg.PID, gcommon.ServerTypeLobby, &protoMsg.PersonSecretLastRankRet{
LastSeasonID: msg.SeasonID,
PID: msg.PID,
LastSeasonRank: mynode.SeasonRank,
LastSeasonEndTime: mynode.UpdatedAt.Unix(),
})
return nil
})
})
}
结论
在gorm的transaction中, Begin会申请一个conn链接, 然后内部如果在获取新的Mysql Conn的话, 当conn达到maxNum的时候,就会卡住, transaction无法自动释放conn,进而导致雪崩,其他的代码想要调用mysql都会出现等待conn的死锁情况.
所以 在 transaction 的代码中, 要用 tx 对象,不要用新的对象.
ps: 这代码是同事写的,但是引以为戒. 顺便 get 到gorm事务的踩坑用法,知道为什么这么写更重要.
------------------------------------------------------------------------------------------------
一定要专业!本博客定位于 ,C语言,C++语言,Java语言,Android开发和少量的Web开发,之前是做Web开发的,其实就是ASP维护,发现EasyASP这个好框架,对前端后端数据库 都很感觉亲切啊。. linux,总之后台开发多一点。以后也愿意学习 cocos2d-x 游戏客户端的开发。