页首Html代码

返回顶部

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事务的踩坑用法,知道为什么这么写更重要.

posted @ 2024-03-14 17:59  ayanmw  阅读(121)  评论(0编辑  收藏  举报

页脚Html代码