[问题][已解决] 并发场景下 "mysql: too many connections" 原因

问题出现是这样的,用node写爬虫, 之前每条数据都是await插入,并且是阻塞的,后来改成了非阻塞,可以并行插入操作,结果一直找不到原因。

后来在日志中找到了 too many connections,分析如下:

用nodejs写爬虫的时候,使用了类似这样的函数

 

let conn = null;

try{

  conn = await pool.getConnection();

  await conn.begin()

  let rst = await .conn.query('xxxx',params);

  // 处理rst

  ...

  await conn.commit()

}catch(e){

  if(conn) await conn.rollback(); 

}finally{

  if(conn) await conn.release();

}

 

 

乍一看没有问题,执行爬虫之后,我会调用这段代码把分析过的数据存在数据库里。

但是由于我是使用非阻塞的形式进行抓取数据的,如下

 

emitter.on('url_found', async (url)=>{

  // 请求url地址,获取返回的response body

  let res = await request(url);

  // 处理res

  ...

  // 后面调用上面的第一段代码

})

 

这里会发生一件事,就是可能同时触发了1000个这样的事件,然后一起获取链接,但是还没有释放,然后报错: too many connections

 

 

============================ 解决方案 ===============================

改造获取sql连接的函数

1. 判断当前连接数是否达到最大,如果否,则直接返回连接池内连接,连接数++

2. 如果上述判断为true,则等待一个promise,将该promise的resolve函数推入等待队列

3. 当某一个连接release的时候,连接数--

4. release中调用pool的notifyFirstWaiting方法,每次取出队列第一个resolve并执行,然后该resolve出列

5. 第二步中的promise的resolve被执行后,则会执行后续代码,此时等待的promise被唤醒,尝试重新获取连接返回

 

 

 

 

 

转载于:https://www.cnblogs.com/kazetotori/p/9333465.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值