前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次golang操作mysql8死锁问题处理流程

记一次golang操作mysql8死锁问题处理流程

原创
作者头像
用户2825890
发布2024-04-10 17:18:04
770
发布2024-04-10 17:18:04
举报
文章被收录于专栏:点滴随笔点滴随笔

现像

第三方平台调用我方平台接口后导致服务不可用,数据库大量sleep线程,请求数据库无响应;数据库及代码无任何报错,无法定位问题。第三方接口首次请求并不会触发该问题。

运行环境

开发语言:golang v1.19

数据库:mysql8

线索搜集

1、对mysql的操作,使用了连接池,并在使用连接之前,调用goalng mysql 的 Ping()检查连接是否可用;

2、发生问题接口的地方使用了事务,开启事务的代码如下:

代码语言:go
复制
func (q *ExQuery) CreateDBTx() (*ExQuery, error) {
	ctx := context.Background()
	q.Ctx = ctx
	conn, e := q.DB.Conn(ctx)
	if e == nil {
	opts := new(sql.TxOptions)
	tx, err := q.DB.BeginTx(ctx, opts)
	if err == nil {
		q.Tx = tx
		return q, nil
	} else {
		return nil, err
	}
	}
	log.Println("===创建事务失败:===", e)
	return nil, e
}

3、show processlist发现连接一直增加并未释放,大量sleep线程;

思路

1、首先要找到大量连接未释的原因;

2、其次解决死锁;

发现问题

代码语言:go
复制
// 查阅开启事务方法时发现
// conn, e := q.DB.Conn(ctx)
// 会新建连接,但在代码中未关闭,但此又处不能关闭,关闭后,连接断开,线程中的查询无效
// 而后将此段代码修改为:
func (q *ExQuery) CreateDBTx() (*ExQuery, error) {
	ctx := context.Background()
	q.Ctx = ctx
	// conn, e := q.DB.Conn(ctx)
	// if e == nil {
	opts := new(sql.TxOptions)
	tx, err := q.DB.BeginTx(ctx, opts)
	if err == nil {
		q.Tx = tx
		return q, nil
	} else {
		return nil, err
	}
	// }
	log.Println("===创建事务失败:===", err)
	return nil, err
}

大量连接未释放问题解决完毕

golang mysql Ping() 此方法在mysql连接不足(因为上面大量sleep)时会永久阻塞;用以前方法替代:

代码语言:go
复制
connerr := dbConnection.DB.PingContext(ctx)

阻塞问题解决

以此记录

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档