node 轮询mysql ,报错,连接数过多

福尔摩斯对我笑 2019-03-11 413 次 1条

前言

在做一个项目时,使用到了连接池,项目中有2个轮询数据库的操作,开始时在本地测试没有问题,都很正常。

项目部署上线后,运行5分钟后发现出错,错误代码:MySQL: ERROR 1040: Too many connections,连接数过多。

查看连接数状态

mysql -u root -p

show full  processlist //查看连接数

发现有大量等待的连接,没有关闭。

看到这我比较奇怪,该项目中我其实轮询了多个数据库,为啥其它数据库没报错,唯有这个连接数过高呢?

检查代码

查看连接池代码,也没有问题,查询后确实已经回收了,有点郁闷,查了 mysql模块的手册,确实也没问题啊。mysql模块手册

 async await_query(sql,values){
        return new Promise((resolve, reject) => {
            this.connect().getConnection(function (err, connection) {
                if (err) {
                    reject(err)
                } else {
                    
                    connection.query(sql, values, (err, rows) => {
                       
                        if (err) {
                            connection.release(); //回收了
                            reject(err);
                        } else {
                            connection.release();
                            resolve(rows);
                           
                        }
                      
                    })
                }
            })

            
           
        })
       
    }
    

也尝试过,直接关闭链接,发现还是不行

connect().end(function (err) {
            console.log(err+"关闭数据库链接");
     });

查看mysql最大连接数,最大为214,仔细对比了下当前的连接数,发现确实超过214个连接,就开始报错

show variables like '%max_connections%';

于是,想了想,把连接数改大一点不就行了,经测试,这样做确实可以。但是看到一堆sleep的请求,强迫症犯了,这样虽能解决,但感觉不好,浪费资源,于是又开始查询资料。

set GLOBAL max_connections = 300;
  • 先来看看sleep的状态是什么意思?
  1. 客户端程序在退出之前没有关闭连接.[写程序的疏忽,或者数据库的db类库没有自动关闭每次的连接。
  2. 客户端sleep的时间在wait_timeout或interactive_timeout规定的秒内没有发出任何请求到服务器. [类似长连,类似于不完整的tcp ip协议构造,服务端一直认为客户端仍然存在(有可能客户端已经断掉了)]
  3. 客户端程序在结束之前向服务器发送了请求还没得到返回结果就结束掉了
  • 解决方法
  1. 修改mysql配置文件: wait_timeout=10 ,这样做需要重启服务器,不太好。
  2. 通过mysql命令修改

set global wait_timeout = 10;

使用第二种方法修改后,重新启动服务,发现确实解决了该问题,现在所有sleep的链接在10秒后都会自动关闭。

注意:使用以上方法时,也会造成其他问题,比如有些场景,连接就必须持久一点。设置成10秒很容易断开。

测试了一段时间,发现还是有问题,所以将回收换成了立即销毁

connection.destroy();

延伸问题

1、修改链接数后,查看当前的配置

show variables like '%timeout%';

发现,wait_timeout 还是 28800 , 默认的8小时。ok,继续搜寻吧 发现一篇博客: https://www.cnblogs.com/agostop/p/4835934.html,这里解释了这个问题

2、数据库查询后我确实已经回收了该链接,为啥还是存在sleep呢? 麻烦知道的大神,解答下,谢谢

今天又尝试了下,问题解决了,是我调用类方法分开进行了引用,导致无法准确获取到链接信息。

标签: 无

非特殊说明,本博所有文章均为博主原创。

头像也是LOGO
未来博客 博主大人
到了这个年纪,不应该再彷徨!

发表评论



 


已有 1 条评论 1


  1. 福尔摩斯对我笑

    testddd

    回复 2019年4月9日