最近在使用go语言操作数据库的时候遇到个隐藏的问题,这种问题很难定位,最后经过多方测试、尝试、猜测最后才确认问题,问题是这样的:

当时我们当时用的go的gin框架做后台服务、使用mysql作为后台数据库,然后在初始化的时候设置了go数据库操作线程池,这个线程池是go语言自带的线程池,我们只需要设置一些参数就可以实现数据库线程池。然后最后测试测出来不知道什么原因,经过一段时间的测试,服务卡死了,所有的访问都无法正常访问;最开始是找路由框架的问题,找了半天也没找到问题,后面又猜测是非法字符操作的问题,最后经过各种测试发现是功能函数里面有个系统函数没用对,导致线程池到达上限,所有访问卡死。具体的导致原因和解决方法如下所示:

我们在线程池设置的地方是这样设置的:

const (dbMaxLiftTime  = 2 * time.HourdbMaxIdleConns = 30dbMaxOpenConns = 100
)G_dbpap, err := sql.Open("mysql", mysqlurl)
if err != nil {golog.Error(err)return err
}
G_dbpap.SetMaxIdleConns(dbMaxIdleConns)   //连接池的空闲数大小
G_dbpap.SetMaxOpenConns(dbMaxOpenConns)   //设置最大打开连接数
G_dbpap.SetConnMaxLifetime(dbMaxLiftTime) //设置连接的最大生存时间

上面的代码中,我们打开了一个G_dbpap的全局操作mysql数据库的变量,然后我们设置了线程池,最大打开访问连接数为100,这个设置是导致我出现问题的关键,另外两个根据字面上的意思也能理解,记住这个100

然后我代码中有个API接口函数是这样写的:

sql_cmd := `DELETE FROM TABLEDATA`
_,err := G_dbpap.Query(sql_cmd)
if err != nil{return err
}

注意这个G_dbpap.Query,我看了他函数源码里面他的第一个返回值是Rows指针,下面附上了源代码

func (db *DB) Query(query string, args ...any) (*Rows, error) {return db.QueryContext(context.Background(), query, args...)
}

我之前也看了很多资料知道这个rows返回值用完必须要手动close,但是就是因为这个地方我图方便,因为是删除语句,我不需要处理返回值就用了下划线略过返回值,其实是有问题的,这个rows不close的话,这一次的请求线程就会一直占用,不会释放,所以接口测试超过100次,这个线程占用就会达到100次,然后上面设置的线程池最大连接数就是100次,所以就导致100次的接口测试后,所有使用G_dbpap句柄操作数据库的访问请求都会卡死。因为设置了最大线程池大小,达到最大后,访问请求就会等到之前的线程释放掉才会响应。

当时的心情真的很激动,折磨好久的问题终于定位到原因,然后怎么解决呢,两种方法:

1、像上面那种数据库操作请求,因为不需要返回值,所有只需将Query换成Exec执行数据库即可,如下所示

sql_cmd := `DELETE FROM TABLEDATA`
_,err := G_dbpap.Exec(sql_cmd)
if err != nil{return err
}

2、如果不像上面的那种,需要处理返回值的数据库操作,如select的,需要再使用完rows后close掉,如下所示

sql_cmd := `SELECT * FROM TABLEDATA`
rows,err := G_dbpap.Query(sql_cmd)
if err != nil{return err
}for rows.Next() {//获取rows的返回值操作}rows.Close()

这样用完操作然后Close掉才不会出现问题。

备注:从上面的情况来看,其实出现原因也是我自己的问题,删除操作数据库的操作函数不该用Query函数,但是其实我也非常感谢我用错,不用错,我就不会深刻理解用了Query没有Close会导致什么严重的后果。还有就是有人或许会说,如果数据库线程池操作那个不设置那100的限制,应该也不会出现这个问题,其实大家再仔细想想,如果前面没有设置那100的限制(好像默认是无上限),那么最后出现问题可能是灾难性的,设想没有释放的线程越来越多,最后导致系统崩了,到那时可能定位问题更是艰难无比了。

以上就是我此次遇到的问题和解决方法,记录于此,希望对后面的朋友有所帮助。

Go数据库线程池操作问题相关推荐

  1. Android官方开发文档Training系列课程中文版:线程执行操作之线程池操作

    原文地址:http://android.xsoftlab.net/training/multiple-threads/run-code.html#StopThread 上节课我们学习了如何定义一个类用 ...

  2. c语言数据库线程池,C语言多线程中运行线程池,在线程池中运行线程池,,传递的结构体参数值为空/NULL/0...

    typedef struct { }LoanInfos; typedef struct{ int cp;//主线程编号 int thread;//线程编号 long int time; int arr ...

  3. python线程池操作_python线程池和进程池

    线程池和进程池 开局来张图 使用线程池的好处 1.提升性能:因为减去了大量新建.终止线程的开销,重用了线程资源 2.使用场景:适合处理突发性大量请求或需要大量线程完成任务.但实际任务处理时间较短 3. ...

  4. python线程池操作_Python mutiprocessing多线程池pool操作示例

    本文实例讲述了Python mutiprocessing多线程池pool操作.分享给大家供大家参考,具体如下: python - mutiprocessing 多线程 pool 脚本代码: root@ ...

  5. 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(11)---各种线程相关操作类...

    俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力. 本篇的公用类库的介绍主题是程序开发中多线程操作环境中,常用到的线程相关类,本篇 ...

  6. Java并发编程-ThreadPool线程池

    ThreadPool线程池 1.线程池的优势 1.1.引言 1.2.为什么要使用线程池 2.线程池的使用 2.1.架构说明 2.2.线程池的三大方法 2.2.1.newFixedThreadPool( ...

  7. JUC探险-17、线程池

    文章目录 一.线程:   ①线程的创建     如果同时继承了Thread类且实现了Runnable接口,会怎样执行?   ②线程状态   ③线程状态的转换     线程状态的转换操作       1 ...

  8. 线程池介绍:ThreadPoolExecutor

    线程池介绍:ThreadPoolExecutor 线程池介绍 多线程技术的不足之处(需要线程池的原因) 什么是线程池 线程池的优势 线程池的架构 线程池的执行原理 线程池状态 任务提交内部原理 exe ...

  9. ExecutorService线程池

    ExecutorService 建立多线程的步骤: 1.定义线程类 class Handler implements Runnable{ } 2.建立ExecutorService线程池 Execut ...

最新文章

  1. Journey源码分析三:模板编译
  2. 【Python-ML】SKlearn库性能指标-混淆矩阵和F1
  3. JAVA多线程--Thinking in java
  4. 流控组件Sentinel核心注解@SentinelResource中的参数fallback和blockHandler的使用方式
  5. matlab中关于程序运行的快捷键
  6. python如何进行web开发_如何用Python做Web开发
  7. 1.1、推断和设置“是否为 Web 环境”
  8. JAVA学习经验--总结JAVA抽象类和接口
  9. 如何让ARM板开机启动Qt
  10. 解方程计算器,一款数学神器APP,有需要的自己收藏!
  11. STM32CubeMX | STM32F1系列HAL库读写内部FLASH
  12. pytorch基础---李博文记录索引
  13. 苹果主屏幕按钮怎么设置_苹果手机屏幕横屏怎么调
  14. Preparatory Class-Day8------函数
  15. IDEA 一直卡在Buil(编译 write classes)报错资源不足
  16. 从零构建通讯器--7.1过往总结和心跳包代码实战
  17. Terracotta 3.2.1简介 (二)
  18. 二维码编码库qrencode
  19. 关于 CC BY-SA 4.0
  20. 基于数字温度传感器的数字温度计 华氏度和摄氏度

热门文章

  1. vue 调用webservice_动态调用WebService接口的几种方式
  2. Unity Shader 布料渲染(丝袜)
  3. 数云融合丨浅谈政府数字化转型
  4. R语言使用dplyr包的summarise函数计算dataframe数据中指定(特定)数据列的移动平均值
  5. 学会了GDB,就像山顶洞人学会了钻木取火
  6. 谈谈产品和运营 - 什么是需求(中)
  7. Verilog 有符号数 signed
  8. 20100919_Dawning_JTable
  9. android App应用实现评分功能
  10. 【基础题目集】7-8 超速判断 (10分)